Compare commits

..

1 commit

Author SHA1 Message Date
hathach
fe2e46d16c
feat(esp32-s2/s3): update tinyuf2 for Adafruit board to 0.20.1 2024-09-06 11:31:27 +07:00
1084 changed files with 12841 additions and 74923 deletions

View file

@ -1,7 +1,7 @@
[codespell] [codespell]
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check/.codespellrc # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check/.codespellrc
# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: # In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here:
ignore-words-list = ba,licence,ot,dout,als,exten,emac ignore-words-list = ba,licence,ot,dout,als,exten
skip = ./.git,./.licenses,__pycache__,.clang-format,.codespellrc,.editorconfig,.flake8,.prettierignore,.yamllint.yml,.gitignore,boards.txt,platform.txt,programmers.txt skip = ./.git,./.licenses,__pycache__,.clang-format,.codespellrc,.editorconfig,.flake8,.prettierignore,.yamllint.yml,.gitignore,boards.txt,platform.txt,programmers.txt
builtin = clear,informal,en-GB_to_en-US builtin = clear,informal,en-GB_to_en-US
check-filenames = check-filenames =

View file

@ -18,7 +18,7 @@ indent_size = 2
indent_style = space indent_style = space
[*.{bash,sh}] [*.{bash,sh}]
indent_size = 4 indent_size = 2
indent_style = space indent_style = space
[*.{c,cc,cp,cpp,cxx,h,hh,hpp,hxx,ii,inl,ino,ixx,pde,tpl,tpp,txx}] [*.{c,cc,cp,cpp,cxx,h,hh,hpp,hxx,ii,inl,ino,ixx,pde,tpl,tpp,txx}]

81
.github/CODEOWNERS vendored
View file

@ -1,81 +0,0 @@
# CODEOWNERS for ESP32 Arduino Core
# This file is used to specify the code owners for the ESP32 Arduino Core.
# Read more about CODEOWNERS:
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# Note that order matters. The last matching pattern will be used.
# The default owners are the active developers of the ESP32 Arduino Core.
# Refrain from using @espressif/arduino-esp32 to avoid spamming non-developers with review requests.
* @espressif/arduino-devs
# CI
/.github/ @lucasssvaz @me-no-dev @P-R-O-C-H-Y
/.github/codeql/ @lucasssvaz
/.gitlab/ @lucasssvaz
/tests/ @lucasssvaz @P-R-O-C-H-Y
# Tools
/tools/ @me-no-dev
/tools/pre-commit/ @lucasssvaz
/tools/add_lib.sh @P-R-O-C-H-Y
# Pre-commit
/.* @lucasssvaz # Files in root directory that start with a dot.
# Git Files
/.gitignore @espressif/arduino-devs
/.gitmodules @espressif/arduino-devs
# Documentation
/docs/ @pedrominatel
/.github/ISSUE_TEMPLATE/ @pedrominatel
/.github/PULL_REQUEST_TEMPLATE.md @pedrominatel
/.readthedocs.yaml @pedrominatel
/*.md @pedrominatel
# Boards
/variants/ @P-R-O-C-H-Y
/boards.txt @P-R-O-C-H-Y
# Arduino as Component
/idf_component_examples/ @SuGlider
/idf_component.yml @SuGlider @me-no-dev
/CMakeLists.txt @SuGlider @me-no-dev
/Kconfig.projbuild @SuGlider @me-no-dev
# Build System
/package.json @me-no-dev
/platform.txt @me-no-dev
/programmers.txt @me-no-dev
/package/ @me-no-dev
# Libraries
/libraries/ArduinoOTA/ @me-no-dev
/libraries/AsyncUDP/ @me-no-dev
/libraries/BLE/ @lucasssvaz @SuGlider
/libraries/ESP_I2S/ @me-no-dev
/libraries/ESP_NOW/ @P-R-O-C-H-Y @lucasssvaz
/libraries/ESP_SR/ @me-no-dev
/libraries/ESPmDNS/ @me-no-dev
/libraries/Ethernet/ @me-no-dev
/libraries/Matter/ @SuGlider
/libraries/NetBIOS/ @me-no-dev
/libraries/Network/ @me-no-dev
/libraries/OpenThread/ @SuGlider
/libraries/PPP/ @me-no-dev
/libraries/SPI/ @me-no-dev
/libraries/Update/ @me-no-dev
/libraries/USB/ @SuGlider @me-no-dev
/libraries/WiFi/ @me-no-dev
/libraries/WiFiProv/ @me-no-dev
/libraries/Wire/ @me-no-dev
/libraries/Zigbee/ @P-R-O-C-H-Y
# CI JSON
# Keep this after other libraries and tests to avoid being overridden.
**/ci.json @lucasssvaz
# The CODEOWNERS file should be owned by the developers of the ESP32 Arduino Core.
# Leave this entry as the last one to avoid being overridden.
/.github/CODEOWNERS @espressif/arduino-devs

View file

@ -5,7 +5,6 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
* Please note that we can only process feature requests reported in English to ensure effective communication and support. Feature requests written in other languages will be closed, with a request to rewrite them in English.
* We welcome any ideas or feature requests! It is helpful if you can explain exactly why the feature would be useful. * We welcome any ideas or feature requests! It is helpful if you can explain exactly why the feature would be useful.
* There are usually some outstanding feature requests in the [existing issues list](https://github.com/espressif/arduino-esp32/issues?q=is%3Aopen+is%3Aissue+label%3A%22Type%3A+Feature+request%22), feel free to add comments to them. * There are usually some outstanding feature requests in the [existing issues list](https://github.com/espressif/arduino-esp32/issues?q=is%3Aopen+is%3Aissue+label%3A%22Type%3A+Feature+request%22), feel free to add comments to them.
* If you would like to contribute, please read the [contributions guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/contributing.html). * If you would like to contribute, please read the [contributions guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/contributing.html).

View file

@ -5,7 +5,6 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
* Please note that we can only process issues reported in English to ensure effective communication and support. Issues written in other languages will be closed, with a request to rewrite them in English.
* Before reporting a new issue please check and search in [List of existing issues](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue) * Before reporting a new issue please check and search in [List of existing issues](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue)
* Please check [Online Documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/index.html) * Please check [Online Documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/index.html)
* Take a look on [Troubleshooting guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/troubleshooting.html) * Take a look on [Troubleshooting guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/troubleshooting.html)
@ -25,7 +24,7 @@ body:
description: What development board or other hardware is the chip attached to? description: What development board or other hardware is the chip attached to?
placeholder: ex. DevKitC, plain module on breadboard, etc. If your hardware is custom or unusual, please attach a photo. placeholder: ex. DevKitC, plain module on breadboard, etc. If your hardware is custom or unusual, please attach a photo.
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: other-hw id: other-hw
attributes: attributes:
@ -40,19 +39,8 @@ body:
label: Version label: Version
description: What version of Arduino ESP32 are you running? If possible, consider updating to the latest version. description: What version of Arduino ESP32 are you running? If possible, consider updating to the latest version.
options: options:
- latest stable Release (if not listed below)
- latest development Release Candidate (RC-X)
- latest master (checkout manually) - latest master (checkout manually)
- v3.3.0 - latest development Release Candidate (RC-X)
- v3.2.1
- v3.2.0
- v3.1.3
- v3.1.2
- v3.1.1
- v3.1.0
- v3.0.7
- v3.0.6
- v3.0.5
- v3.0.4 - v3.0.4
- v3.0.3 - v3.0.3
- v3.0.2 - v3.0.2
@ -80,25 +68,14 @@ body:
- other - other
validations: validations:
required: true required: true
- type: dropdown
id: type
attributes:
label: Type
description: How would you define the type of the issue? Please select from the types below.
options:
- Task
- Bug
- Question
validations:
required: true
- type: input - type: input
id: IDE id: IDE
attributes: attributes:
label: IDE Name label: IDE Name
description: What IDE are you using? description: What IDE are you using?
placeholder: eg. Arduino IDE, VSCode, Sloeber... placeholder: eg. Arduino IDE, PlatformIO, Sloeber...
validations: validations:
required: true required: true
- type: input - type: input
id: os id: os
attributes: attributes:
@ -121,8 +98,8 @@ body:
label: PSRAM enabled label: PSRAM enabled
description: Is PSRAM enabled? description: Is PSRAM enabled?
options: options:
- "yes" - 'yes'
- "no" - 'no'
validations: validations:
required: true required: true
- type: input - type: input
@ -137,8 +114,8 @@ body:
id: Description id: Description
attributes: attributes:
label: Description label: Description
description: Please describe your problem here and expected behavior description: Please describe your problem here and expected behaviour
placeholder: ex. Can't connect/weird behavior/wrong function/missing parameter.. placeholder: ex. Can't connect/weird behaviour/wrong function/missing parameter..
validations: validations:
required: true required: true
- type: textarea - type: textarea
@ -149,7 +126,7 @@ body:
placeholder: ex. Related part of the code to replicate the issue placeholder: ex. Related part of the code to replicate the issue
render: cpp render: cpp
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: Debug id: Debug
attributes: attributes:

View file

@ -1,5 +1,8 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Arduino Core for Espressif Discord Server - name: Arduino ESP32 Gitter Channel
url: https://discord.gg/8xY6e9crwv url: https://gitter.im/espressif/arduino-esp32
about: Community Discord server for questions and help about: Community channel for questions and help
- name: ESP32 Forum - Arduino
url: https://esp32.com/viewforum.php?f=19
about: Official Forum for questions

View file

@ -1,26 +0,0 @@
name: "CodeQL config"
packs:
- trailofbits/cpp-queries
- githubsecuritylab/codeql-cpp-queries
- githubsecuritylab/codeql-python-queries
queries:
- uses: security-extended
- uses: security-and-quality
query-filters:
- exclude:
query path:
- /^experimental\/.*/
- exclude:
tags contain:
- experimental
- exclude:
problem.severity:
- recommendation
- exclude:
id: tob/cpp/use-of-legacy-algorithm
paths-ignore:
- tests/**

View file

@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
# #
# This script is used in the CI workflow. It checks all non-examples source files in libraries/ and cores/ are listed in # This script is used in the CI workflow. It checks all non-examples source files in libraries/ and cores/ are listed in
# CMakeLists.txt for the cmake-based IDF component # CMakeLists.txt for the cmake-based IDF component
@ -13,10 +12,10 @@ set -e
git submodule update --init --recursive git submodule update --init --recursive
# find all source files in repo # find all source files in repo
REPO_SRCS=$(find cores/esp32/ libraries/ -name 'examples' -prune -o -name '*.c' -print -o -name '*.cpp' -print | sort) REPO_SRCS=`find cores/esp32/ libraries/ -name 'examples' -prune -o -name '*.c' -print -o -name '*.cpp' -print | sort`
# find all source files named in CMakeLists.txt COMPONENT_SRCS # find all source files named in CMakeLists.txt COMPONENT_SRCS
CMAKE_SRCS=$(cmake --trace-expand -P CMakeLists.txt 2>&1 | grep set\(srcs | cut -d'(' -f3 | sed 's/ )//' | sed 's/srcs //' | tr ' ;' '\n' | sort) CMAKE_SRCS=`cmake --trace-expand -P CMakeLists.txt 2>&1 | grep set\(srcs | cut -d'(' -f3 | sed 's/ )//' | sed 's/srcs //' | tr ' ;' '\n' | sort`
if ! diff -u0 --label "Repo Files" --label "srcs" <(echo "$REPO_SRCS") <(echo "$CMAKE_SRCS"); then if ! diff -u0 --label "Repo Files" --label "srcs" <(echo "$REPO_SRCS") <(echo "$CMAKE_SRCS"); then
echo "Source files in repo (-) and source files in CMakeLists.txt (+) don't match" echo "Source files in repo (-) and source files in CMakeLists.txt (+) don't match"

View file

@ -3,9 +3,7 @@
# Get all boards # Get all boards
boards_array=() boards_array=()
boards_list=$(grep '.tarch=' boards.txt) for line in `grep '.tarch=' boards.txt`; do
while read -r line; do
board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1) board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1)
# skip esp32c2 as we dont build libs for it # skip esp32c2 as we dont build libs for it
if [ "$board_name" == "esp32c2" ]; then if [ "$board_name" == "esp32c2" ]; then
@ -14,26 +12,29 @@ while read -r line; do
fi fi
boards_array+=("espressif:esp32:$board_name") boards_array+=("espressif:esp32:$board_name")
echo "Added 'espressif:esp32:$board_name' to array" echo "Added 'espressif:esp32:$board_name' to array"
done <<< "$boards_list" done
# Create JSON like string with all boards found and pass it to env variable # Create JSON like string with all boards found and pass it to env variable
board_count=${#boards_array[@]} board_count=${#boards_array[@]}
echo "Boards found: $board_count" echo "Boards found: $board_count"
echo "BOARD-COUNT=$board_count" >> "$GITHUB_ENV" echo "BOARD-COUNT=$board_count" >> $GITHUB_ENV
if [ "$board_count" -gt 0 ]; then if [ $board_count -gt 0 ]
then
json_matrix='[' json_matrix='['
for board in "${boards_array[@]}"; do for board in ${boards_array[@]}
do
json_matrix+='"'$board'"' json_matrix+='"'$board'"'
if [ "$board_count" -gt 1 ]; then if [ $board_count -gt 1 ]
then
json_matrix+="," json_matrix+=","
fi fi
board_count=$((board_count - 1)) board_count=$(($board_count - 1))
done done
json_matrix+=']' json_matrix+=']'
echo "$json_matrix" echo $json_matrix
echo "FQBNS=${json_matrix}" >> "$GITHUB_ENV" echo "FQBNS=${json_matrix}" >> $GITHUB_ENV
else else
echo "FQBNS=" >> "$GITHUB_ENV" echo "FQBNS=" >> $GITHUB_ENV
fi fi

View file

@ -2,61 +2,89 @@
# Get inputs from command # Get inputs from command
owner_repository=$1 owner_repository=$1
base_ref=$2 pr_number=$2
# Download the boards.txt file from the base branch url="https://api.github.com/repos/$owner_repository/pulls/$pr_number/files"
curl -L -o boards_base.txt https://raw.githubusercontent.com/"$owner_repository"/"$base_ref"/boards.txt echo $url
# Compare boards.txt file in the repo with the modified file from PR # Get changes in boards.txt file from PR
diff=$(diff -u boards_base.txt boards.txt) Patch=$(curl $url | jq -r '.[] | select(.filename == "boards.txt") | .patch ')
# Check if the diff is empty # Extract only changed lines number and count
if [ -z "$diff" ]; then substring_patch=$(echo "$Patch" | grep -o '@@[^@]*@@')
echo "No changes in boards.txt file"
echo "FQBNS="
exit 0
fi
# Extract added or modified lines (lines starting with '+' or '-') params_array=()
modified_lines=$(echo "$diff" | grep -E '^[+-][^+-]')
# Print the modified lines for debugging IFS=$'\n' read -d '' -ra params <<< $(echo "$substring_patch" | grep -oE '[-+][0-9]+,[0-9]+')
echo "Modified lines:"
echo "$modified_lines" for param in "${params[@]}"
do
echo "The parameter is $param"
params_array+=("$param")
done
boards_array=() boards_array=()
previous_board="" previous_board=""
file="boards.txt"
# Extract board names from the modified lines, and add them to the boards_array # Loop through boards.txt file and extract all boards that were added
while read -r line; do for (( c=0; c<${#params_array[@]}; c+=2 ))
do
deletion_count=$( echo "${params_array[c]}" | cut -d',' -f2 | cut -d' ' -f1 )
addition_line=$( echo "${params_array[c+1]}" | cut -d'+' -f2 | cut -d',' -f1 )
addition_count=$( echo "${params_array[c+1]}" | cut -d'+' -f2 | cut -d',' -f2 | cut -d' ' -f1 )
addition_end=$(($addition_line+$addition_count))
addition_line=$(($addition_line + 3))
addition_end=$(($addition_end - $deletion_count))
echo $addition_line
echo $addition_end
i=0
while read -r line
do
i=$((i+1))
if [ $i -lt $addition_line ]
then
continue
elif [ $i -gt $addition_end ]
then
break
fi
board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1) board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1)
# remove + or - from the board name at the beginning if [ "$board_name" != "" ] && [ "$board_name" != "esp32_family" ]
board_name=${board_name#[-+]} then
if [ "$board_name" != "" ] && [ "$board_name" != "+" ] && [ "$board_name" != "-" ] && [ "$board_name" != "esp32_family" ]; then if [ "$board_name" != "$previous_board" ]
if [ "$board_name" != "$previous_board" ]; then then
boards_array+=("espressif:esp32:$board_name") boards_array+=("espressif:esp32:$board_name")
previous_board="$board_name" previous_board="$board_name"
echo "Added 'espressif:esp32:$board_name' to array" echo "Added 'espressif:esp32:$board_name' to array"
fi fi
fi fi
done <<< "$modified_lines" done < "$file"
done
# Create JSON like string with all boards found and pass it to env variable # Create JSON like string with all boards found and pass it to env variable
board_count=${#boards_array[@]} board_count=${#boards_array[@]}
if [ "$board_count" -gt 0 ]; then if [ $board_count -gt 0 ]
then
json_matrix='{"fqbn": [' json_matrix='{"fqbn": ['
for board in "${boards_array[@]}"; do for board in ${boards_array[@]}
do
json_matrix+='"'$board'"' json_matrix+='"'$board'"'
if [ "$board_count" -gt 1 ]; then if [ $board_count -gt 1 ]
then
json_matrix+="," json_matrix+=","
fi fi
board_count=$((board_count - 1)) board_count=$(($board_count - 1))
done done
json_matrix+=']}' json_matrix+=']}'
echo "$json_matrix" echo $json_matrix
echo "FQBNS=${json_matrix}" >> "$GITHUB_ENV" echo "FQBNS=${json_matrix}" >> $GITHUB_ENV
else else
echo "FQBNS=" >> "$GITHUB_ENV" echo "FQBNS=" >> $GITHUB_ENV
fi fi

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
OSBITS=$(uname -m) OSBITS=`uname -m`
if [[ "$OSTYPE" == "linux"* ]]; then if [[ "$OSTYPE" == "linux"* ]]; then
export OS_IS_LINUX="1" export OS_IS_LINUX="1"
if [[ "$OSBITS" == "i686" ]]; then if [[ "$OSBITS" == "i686" ]]; then
@ -49,3 +49,4 @@ if [ ! -d "$ARDUINO_IDE_PATH" ] || [ ! -f "$ARDUINO_IDE_PATH/arduino-cli" ]; the
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR="$ARDUINO_IDE_PATH" sh curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR="$ARDUINO_IDE_PATH" sh
fi fi
fi fi

View file

@ -5,7 +5,7 @@ if [ ! -d "$ARDUINO_ESP32_PATH" ]; then
echo "Installing ESP32 Arduino Core ..." echo "Installing ESP32 Arduino Core ..."
script_init_path="$PWD" script_init_path="$PWD"
mkdir -p "$ARDUINO_USR_PATH/hardware/espressif" mkdir -p "$ARDUINO_USR_PATH/hardware/espressif"
cd "$ARDUINO_USR_PATH/hardware/espressif" || exit cd "$ARDUINO_USR_PATH/hardware/espressif"
echo "Installing Python Serial ..." echo "Installing Python Serial ..."
pip install pyserial > /dev/null pip install pyserial > /dev/null
@ -15,25 +15,25 @@ if [ ! -d "$ARDUINO_ESP32_PATH" ]; then
pip install requests > /dev/null pip install requests > /dev/null
fi fi
if [ -n "$GITHUB_REPOSITORY" ]; then if [ ! -z "$GITHUB_REPOSITORY" ]; then
echo "Linking Core..." echo "Linking Core..."
ln -s "$GITHUB_WORKSPACE" esp32 ln -s $GITHUB_WORKSPACE esp32
else else
echo "Cloning Core Repository..." echo "Cloning Core Repository..."
git clone https://github.com/espressif/arduino-esp32.git esp32 > /dev/null 2>&1 git clone https://github.com/espressif/arduino-esp32.git esp32 > /dev/null 2>&1
fi fi
#echo "Updating Submodules ..." #echo "Updating Submodules ..."
cd esp32 || exit cd esp32
#git submodule update --init --recursive > /dev/null 2>&1 #git submodule update --init --recursive > /dev/null 2>&1
echo "Installing Platform Tools ..." echo "Installing Platform Tools ..."
if [ "$OS_IS_WINDOWS" == "1" ]; then if [ "$OS_IS_WINDOWS" == "1" ]; then
cd tools && ./get.exe cd tools && ./get.exe
else else
cd tools && python get.py cd tools && python get.py
fi fi
cd "$script_init_path" || exit cd $script_init_path
echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'" echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'"
echo "" echo ""

View file

@ -4,7 +4,7 @@
#OSTYPE: 'msys', ARCH: 'x86_64' => win32 #OSTYPE: 'msys', ARCH: 'x86_64' => win32
#OSTYPE: 'darwin18', ARCH: 'i386' => macos #OSTYPE: 'darwin18', ARCH: 'i386' => macos
OSBITS=$(uname -m) OSBITS=`uname -m`
if [[ "$OSTYPE" == "linux"* ]]; then if [[ "$OSTYPE" == "linux"* ]]; then
export OS_IS_LINUX="1" export OS_IS_LINUX="1"
ARCHIVE_FORMAT="tar.xz" ARCHIVE_FORMAT="tar.xz"
@ -77,3 +77,4 @@ if [ ! -d "$ARDUINO_IDE_PATH" ]; then
echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'" echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'"
echo "" echo ""
fi fi

184
.github/scripts/install-platformio-esp32.sh vendored Executable file
View file

@ -0,0 +1,184 @@
#!/bin/bash
export PLATFORMIO_ESP32_PATH="$HOME/.platformio/packages/framework-arduinoespressif32"
PLATFORMIO_ESP32_URL="https://github.com/platformio/platform-espressif32.git"
TOOLCHAIN_VERSION="12.2.0+20230208"
ESPTOOLPY_VERSION="~1.40501.0"
ESPRESSIF_ORGANIZATION_NAME="espressif"
echo "Installing Python Wheel ..."
pip install wheel > /dev/null 2>&1
echo "Installing PlatformIO ..."
pip install -U https://github.com/platformio/platformio/archive/master.zip > /dev/null 2>&1
echo "Installing Platform ESP32 ..."
python -m platformio platform install $PLATFORMIO_ESP32_URL > /dev/null 2>&1
echo "Replacing the package versions ..."
replace_script="import json; import os;"
replace_script+="fp=open(os.path.expanduser('~/.platformio/platforms/espressif32/platform.json'), 'r+');"
replace_script+="data=json.load(fp);"
# Use framework sources from the repository
replace_script+="data['packages']['framework-arduinoespressif32']['version'] = '*';"
replace_script+="del data['packages']['framework-arduinoespressif32']['owner'];"
# Use toolchain packages from the "espressif" organization
replace_script+="data['packages']['toolchain-xtensa-esp32']['owner']='$ESPRESSIF_ORGANIZATION_NAME';"
replace_script+="data['packages']['toolchain-xtensa-esp32s2']['owner']='$ESPRESSIF_ORGANIZATION_NAME';"
replace_script+="data['packages']['toolchain-riscv32-esp']['owner']='$ESPRESSIF_ORGANIZATION_NAME';"
# Update versions to use the upstream
replace_script+="data['packages']['toolchain-xtensa-esp32']['version']='$TOOLCHAIN_VERSION';"
replace_script+="data['packages']['toolchain-xtensa-esp32s2']['version']='$TOOLCHAIN_VERSION';"
replace_script+="data['packages']['toolchain-xtensa-esp32s3']['version']='$TOOLCHAIN_VERSION';"
replace_script+="data['packages']['toolchain-riscv32-esp']['version']='$TOOLCHAIN_VERSION';"
# Add new "framework-arduinoespressif32-libs" package
# Read "package_esp32_index.template.json" to extract a url to a zip package for "esp32-arduino-libs"
replace_script+="fpackage=open(os.path.join('package', 'package_esp32_index.template.json'), 'r+');"
replace_script+="package_data=json.load(fpackage);"
replace_script+="fpackage.close();"
replace_script+="libs_package_archive_url=next(next(system['url'] for system in tool['systems'] if system['host'] == 'x86_64-pc-linux-gnu') for tool in package_data['packages'][0]['tools'] if tool['name'] == 'esp32-arduino-libs');"
replace_script+="data['packages'].update({'framework-arduinoespressif32-libs':{'type':'framework','optional':False,'version':libs_package_archive_url}});"
replace_script+="data['packages']['toolchain-xtensa-esp32'].update({'optional':False});"
# esptool.py may require an upstream version (for now platformio is the owner)
replace_script+="data['packages']['tool-esptoolpy']['version']='$ESPTOOLPY_VERSION';"
# Save results
replace_script+="fp.seek(0);fp.truncate();json.dump(data, fp, indent=2);fp.close()"
python -c "$replace_script"
if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then
echo "Linking Core..."
ln -s $GITHUB_WORKSPACE "$PLATFORMIO_ESP32_PATH"
else
echo "Cloning Core Repository ..."
git clone --recursive https://github.com/espressif/arduino-esp32.git "$PLATFORMIO_ESP32_PATH" > /dev/null 2>&1
fi
echo "PlatformIO for ESP32 has been installed"
echo ""
function build_pio_sketch(){ # build_pio_sketch <board> <options> <path-to-ino>
if [ "$#" -lt 3 ]; then
echo "ERROR: Illegal number of parameters"
echo "USAGE: build_pio_sketch <board> <options> <path-to-ino>"
return 1
fi
local board="$1"
local options="$2"
local sketch="$3"
local sketch_dir=$(dirname "$sketch")
echo ""
echo "Compiling '"$(basename "$sketch")"' ..."
python -m platformio ci --board "$board" "$sketch_dir" --project-option="$options"
}
function count_sketches(){ # count_sketches <examples-path>
local examples="$1"
rm -rf sketches.txt
if [ ! -d "$examples" ]; then
touch sketches.txt
return 0
fi
local sketches=$(find $examples -name *.ino)
local sketchnum=0
for sketch in $sketches; do
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
continue
fi
is_target=$(jq -r --arg target $target '.targets[$target]' $sketchdir/ci.json)
# If the target is listed as false, skip the sketch. Otherwise, include it.
if [[ "$is_target" == "false" ]]; then
continue
fi
echo $sketch >> sketches.txt
sketchnum=$(($sketchnum + 1))
done
return $sketchnum
}
function build_pio_sketches(){ # build_pio_sketches <board> <options> <examples-path> <chunk> <total-chunks>
if [ "$#" -lt 3 ]; then
echo "ERROR: Illegal number of parameters"
echo "USAGE: build_pio_sketches <board> <options> <examples-path> [<chunk> <total-chunks>]"
return 1
fi
local board=$1
local options="$2"
local examples=$3
local chunk_idex=$4
local chunks_num=$5
if [ "$#" -lt 5 ]; then
chunk_idex="0"
chunks_num="1"
fi
if [ "$chunks_num" -le 0 ]; then
echo "ERROR: Chunks count must be positive number"
return 1
fi
if [ "$chunk_idex" -ge "$chunks_num" ]; then
echo "ERROR: Chunk index must be less than chunks count"
return 1
fi
set +e
count_sketches "$examples"
local sketchcount=$?
set -e
local sketches=$(cat sketches.txt)
rm -rf sketches.txt
local chunk_size=$(( $sketchcount / $chunks_num ))
local all_chunks=$(( $chunks_num * $chunk_size ))
if [ "$all_chunks" -lt "$sketchcount" ]; then
chunk_size=$(( $chunk_size + 1 ))
fi
local start_index=$(( $chunk_idex * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then
echo "Skipping job"
return 0
fi
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then
end_index=$sketchcount
fi
local start_num=$(( $start_index + 1 ))
echo "Found $sketchcount Sketches";
echo "Chunk Count : $chunks_num"
echo "Chunk Size : $chunk_size"
echo "Start Sketch: $start_num"
echo "End Sketch : $end_index"
local sketchnum=0
for sketch in $sketches; do
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
is_target=$(jq -r --arg target $target '.targets[$target]' $sketchdir/ci.json)
# If the target is listed as false, skip the sketch. Otherwise, include it.
if [ "${sketchdirname}.ino" != "$sketchname" ] \
|| [[ "$is_target" == "false" ]]; then
continue
fi
sketchnum=$(($sketchnum + 1))
if [ "$sketchnum" -le "$start_index" ] \
|| [ "$sketchnum" -gt "$end_index" ]; then
continue
fi
build_pio_sketch "$board" "$options" "$sketch"
local result=$?
if [ $result -ne 0 ]; then
return $result
fi
done
return 0
}

View file

@ -1,55 +1,47 @@
#!/usr/bin/env python #!/usr/bin/env python
# This script merges two Arduino Board Manager package json files. # This script merges two Arduino Board Manager package json files.
# Usage: # Usage:
# python merge_packages.py package_esp8266com_index.json version/new/package_esp8266com_index.json # python merge_packages.py package_esp8266com_index.json version/new/package_esp8266com_index.json
# Written by Ivan Grokhotkov, 2015 # Written by Ivan Grokhotkov, 2015
# Updated by lucasssvaz to handle Chinese version sorting, 2025
# #
from __future__ import print_function from __future__ import print_function
#from distutils.version import LooseVersion
# from distutils.version import LooseVersion
from packaging.version import Version from packaging.version import Version
import re import re
import json import json
import sys import sys
def load_package(filename): def load_package(filename):
pkg = json.load(open(filename))["packages"][0] pkg = json.load(open(filename))['packages'][0]
print("Loaded package {0} from {1}".format(pkg["name"], filename), file=sys.stderr) print("Loaded package {0} from {1}".format(pkg['name'], filename), file=sys.stderr)
print("{0} platform(s), {1} tools".format(len(pkg["platforms"]), len(pkg["tools"])), file=sys.stderr) print("{0} platform(s), {1} tools".format(len(pkg['platforms']), len(pkg['tools'])), file=sys.stderr)
return pkg return pkg
def merge_objects(versions, obj): def merge_objects(versions, obj):
for o in obj: for o in obj:
name = o["name"].encode("ascii") name = o['name'].encode('ascii')
ver = o["version"].encode("ascii") ver = o['version'].encode('ascii')
if name not in versions: if not name in versions:
print("found new object, {0}".format(name), file=sys.stderr) print("found new object, {0}".format(name), file=sys.stderr)
versions[name] = {} versions[name] = {}
if ver not in versions[name]: if not ver in versions[name]:
print("found new version {0} for object {1}".format(ver, name), file=sys.stderr) print("found new version {0} for object {1}".format(ver, name), file=sys.stderr)
versions[name][ver] = o versions[name][ver] = o
return versions return versions
# Normalize ESP release version string (x.x.x) by adding '-rc<MAXINT>' (x.x.x-rc9223372036854775807) to ensure having REL above any RC
# Normalize ESP release version string (x.x.x) by adding '-rc<MAXINT>' (x.x.x-rc9223372036854775807) # Dummy approach, functional anyway for current ESP package versioning (unlike NormalizedVersion/LooseVersion/StrictVersion & similar crap)
# to ensure having REL above any RC. CN version will be sorted after the official version if they happen
# to be mixed (normally, CN and non-CN versions should not be mixed)
# Dummy approach, functional anyway for current ESP package versioning
# (unlike NormalizedVersion/LooseVersion/StrictVersion & similar crap)
def pkgVersionNormalized(versionString): def pkgVersionNormalized(versionString):
verStr = str(versionString).replace("-cn", "")
verParts = re.split(r"\.|-rc|-alpha", verStr, flags=re.IGNORECASE) verStr = str(versionString)
verParts = re.split('\.|-rc|-alpha', verStr, flags=re.IGNORECASE)
if len(verParts) == 3: if len(verParts) == 3:
if "-cn" in str(versionString): if (sys.version_info > (3, 0)): # Python 3
verStr = verStr + "-rc" + str(sys.maxsize // 2) verStr = str(versionString) + '-rc' + str(sys.maxsize)
else: else: # Python 2
verStr = verStr + "-rc" + str(sys.maxsize) verStr = str(versionString) + '-rc' + str(sys.maxint)
elif len(verParts) != 4: elif len(verParts) != 4:
print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr) print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr)
@ -64,35 +56,29 @@ def main(args):
tools = {} tools = {}
platforms = {} platforms = {}
pkg1 = load_package(args[1]) pkg1 = load_package(args[1])
tools = merge_objects(tools, pkg1["tools"]) tools = merge_objects(tools, pkg1['tools']);
platforms = merge_objects(platforms, pkg1["platforms"]) platforms = merge_objects(platforms, pkg1['platforms']);
pkg2 = load_package(args[2]) pkg2 = load_package(args[2])
tools = merge_objects(tools, pkg2["tools"]) tools = merge_objects(tools, pkg2['tools']);
platforms = merge_objects(platforms, pkg2["platforms"]) platforms = merge_objects(platforms, pkg2['platforms']);
pkg1["tools"] = [] pkg1['tools'] = []
pkg1["platforms"] = [] pkg1['platforms'] = []
for name in tools: for name in tools:
for version in tools[name]: for version in tools[name]:
print("Adding tool {0}-{1}".format(name, version), file=sys.stderr) print("Adding tool {0}-{1}".format(name, version), file=sys.stderr)
pkg1["tools"].append(tools[name][version]) pkg1['tools'].append(tools[name][version])
for name in platforms: for name in platforms:
for version in platforms[name]: for version in platforms[name]:
print("Adding platform {0}-{1}".format(name, version), file=sys.stderr) print("Adding platform {0}-{1}".format(name, version), file=sys.stderr)
pkg1["platforms"].append(platforms[name][version]) pkg1['platforms'].append(platforms[name][version])
# pkg1["platforms"] = sorted( #pkg1['platforms'] = sorted(pkg1['platforms'], key=lambda k: LooseVersion(pkgVersionNormalized(k['version'])), reverse=True)
# pkg1["platforms"], key=lambda k: LooseVersion(pkgVersionNormalized(k["version"])), reverse=True pkg1['platforms'] = sorted(pkg1['platforms'], key=lambda k: Version(pkgVersionNormalized(k['version'])), reverse=True)
# )
pkg1["platforms"] = sorted( json.dump({'packages':[pkg1]}, sys.stdout, indent=2)
pkg1["platforms"], key=lambda k: Version(pkgVersionNormalized(k["version"])), reverse=True
)
json.dump({"packages": [pkg1]}, sys.stdout, indent=2) if __name__ == '__main__':
if __name__ == "__main__":
sys.exit(main(sys.argv)) sys.exit(main(sys.argv))

View file

@ -1,13 +1,12 @@
#!/bin/bash #/bin/bash
set -e set -e
function get_file_size { function get_file_size(){
local file="$1" local file="$1"
if [[ "$OSTYPE" == "darwin"* ]]; then if [[ "$OSTYPE" == "darwin"* ]]; then
eval "$(stat -s "$file")" eval `stat -s "$file"`
local res="$?" local res="$?"
echo "${st_size:?}" echo "$st_size"
return $res return $res
else else
stat --printf="%s" "$file" stat --printf="%s" "$file"
@ -16,32 +15,25 @@ function get_file_size {
} }
#git_remove_from_pages <file> #git_remove_from_pages <file>
function git_remove_from_pages { function git_remove_from_pages(){
local path=$1 local path=$1
local info local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
local type local type=`echo "$info" | jq -r '.type'`
local sha if [ ! $type == "file" ]; then
local message if [ ! $type == "null" ]; then
info=$(curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages")
type=$(echo "$info" | jq -r '.type')
if [ ! "$type" == "file" ]; then
if [ ! "$type" == "null" ]; then
echo "Wrong type '$type'" echo "Wrong type '$type'"
else else
echo "File is not on Pages" echo "File is not on Pages"
fi fi
return 0 return 0
fi fi
local sha=`echo "$info" | jq -r '.sha'`
sha=$(echo "$info" | jq -r '.sha') local message="Deleting "$(basename $path)
message="Deleting "$(basename "$path")
local json="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"sha\":\"$sha\"}" local json="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"sha\":\"$sha\"}"
echo "$json" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X DELETE --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path" echo "$json" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X DELETE --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
} }
function git_upload_to_pages { function git_upload_to_pages(){
local path=$1 local path=$1
local src=$2 local src=$2
@ -50,50 +42,41 @@ function git_upload_to_pages {
return 1 return 1
fi fi
local info local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
local type local type=`echo "$info" | jq -r '.type'`
local message local message=$(basename $path)
local sha="" local sha=""
local content="" local content=""
info=$(curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages") if [ $type == "file" ]; then
type=$(echo "$info" | jq -r '.type') sha=`echo "$info" | jq -r '.sha'`
message=$(basename "$path")
if [ "$type" == "file" ]; then
sha=$(echo "$info" | jq -r '.sha')
sha=",\"sha\":\"$sha\"" sha=",\"sha\":\"$sha\""
message="Updating $message" message="Updating $message"
elif [ ! "$type" == "null" ]; then elif [ ! $type == "null" ]; then
>&2 echo "Wrong type '$type'" >&2 echo "Wrong type '$type'"
return 1 return 1
else else
message="Creating $message" message="Creating $message"
fi fi
content=$(base64 -i "$src") content=`base64 -i "$src"`
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}" data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path" echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
} }
function git_safe_upload_to_pages { function git_safe_upload_to_pages(){
local path=$1 local path=$1
local file="$2" local file="$2"
local name local name=$(basename "$file")
local size local size=`get_file_size "$file"`
local upload_res local upload_res=`git_upload_to_pages "$path" "$file"`
if [ $? -ne 0 ]; then
name=$(basename "$file")
size=$(get_file_size "$file")
if ! upload_res=$(git_upload_to_pages "$path" "$file"); then
>&2 echo "ERROR: Failed to upload '$name' ($?)" >&2 echo "ERROR: Failed to upload '$name' ($?)"
return 1 return 1
fi fi
up_size=`echo "$upload_res" | jq -r '.content.size'`
up_size=$(echo "$upload_res" | jq -r '.content.size') if [ $up_size -ne $size ]; then
if [ "$up_size" -ne "$size" ]; then
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size" >&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
#git_delete_asset #git_delete_asset
return 1 return 1

View file

@ -1,33 +0,0 @@
#!/bin/bash
set -e
CHECK_REQUIREMENTS="./components/arduino-esp32/.github/scripts/sketch_utils.sh check_requirements"
# Export IDF environment
. ${IDF_PATH}/export.sh
# Find all examples in ./components/arduino-esp32/idf_component_examples
idf_component_examples=$(find ./components/arduino-esp32/idf_component_examples -mindepth 1 -maxdepth 1 -type d)
for example in $idf_component_examples; do
if [ -f "$example"/ci.json ]; then
# If the target is listed as false, skip the sketch. Otherwise, include it.
is_target=$(jq -r --arg target "$IDF_TARGET" '.targets[$target]' "$example"/ci.json)
if [[ "$is_target" == "false" ]]; then
printf "\n\033[93mSkipping %s for target %s\033[0m\n\n" "$example" "$IDF_TARGET"
continue
fi
fi
idf.py -C "$example" set-target "$IDF_TARGET"
has_requirements=$(${CHECK_REQUIREMENTS} "$example" "$example/sdkconfig")
if [ "$has_requirements" -eq 0 ]; then
printf "\n\033[93m%s does not meet the requirements for %s. Skipping...\033[0m\n\n" "$example" "$IDF_TARGET"
continue
fi
printf "\n\033[95mBuilding %s\033[0m\n\n" "$example"
idf.py -C "$example" -DEXTRA_COMPONENT_DIRS="$PWD/components" build
done

View file

@ -4,45 +4,43 @@ set -e
export ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp" export ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp"
function build { function build(){
local target=$1 local target=$1
local chunk_index=$2 local chunk_index=$2
local chunks_cnt=$3 local chunks_cnt=$3
local build_log=$4 local build_log=$4
local log_level=${5:-none} local sketches_file=$5
local sketches_file=$6 shift; shift; shift; shift; shift;
shift 6 local sketches=$*
local sketches=("$@")
local BUILD_SKETCH="${SCRIPTS_DIR}/sketch_utils.sh build" local BUILD_SKETCH="${SCRIPTS_DIR}/sketch_utils.sh build"
local BUILD_SKETCHES="${SCRIPTS_DIR}/sketch_utils.sh chunk_build" local BUILD_SKETCHES="${SCRIPTS_DIR}/sketch_utils.sh chunk_build"
local args=("-ai" "$ARDUINO_IDE_PATH" "-au" "$ARDUINO_USR_PATH" "-t" "$target") local args="-ai $ARDUINO_IDE_PATH -au $ARDUINO_USR_PATH"
args+=" -t $target"
if [ "$OS_IS_LINUX" == "1" ]; then if [ "$OS_IS_LINUX" == "1" ]; then
args+=("-p" "$ARDUINO_ESP32_PATH/libraries" "-i" "$chunk_index" "-m" "$chunks_cnt" "-d" "$log_level") args+=" -p $ARDUINO_ESP32_PATH/libraries"
args+=" -i $chunk_index -m $chunks_cnt"
if [ -n "$sketches_file" ]; then if [ -n "$sketches_file" ]; then
args+=("-f" "$sketches_file") args+=" -f $sketches_file"
fi fi
if [ "$build_log" -eq 1 ]; then if [ $build_log -eq 1 ]; then
args+=("-l" "$build_log") args+=" -l $build_log"
fi fi
${BUILD_SKETCHES} "${args[@]}" ${BUILD_SKETCHES} ${args}
else else
for sketch in "${sketches[@]}"; do for sketch in ${sketches}; do
local sargs=("${args[@]}") local sargs="$args -s $(dirname $sketch)"
local ctags_version
local preprocessor_version
sargs+=("-s" "$(dirname "$sketch")")
if [ "$OS_IS_WINDOWS" == "1" ] && [ -d "$ARDUINO_IDE_PATH/tools-builder" ]; then if [ "$OS_IS_WINDOWS" == "1" ] && [ -d "$ARDUINO_IDE_PATH/tools-builder" ]; then
ctags_version=$(ls "$ARDUINO_IDE_PATH/tools-builder/ctags/") local ctags_version=`ls "$ARDUINO_IDE_PATH/tools-builder/ctags/"`
preprocessor_version=$(ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/") local preprocessor_version=`ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/"`
sargs+=( win_opts="-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version
"-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version" -prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version"
"-prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version" sargs+=" ${win_opts}"
)
fi fi
${BUILD_SKETCH} "${sargs[@]}" ${BUILD_SKETCH} ${sargs}
done done
fi fi
} }
@ -55,13 +53,15 @@ fi
CHUNK_INDEX=$1 CHUNK_INDEX=$1
CHUNKS_CNT=$2 CHUNKS_CNT=$2
BUILD_LOG=$3 BUILD_LOG=$3
LOG_LEVEL=$4 SKETCHES_FILE=$4
SKETCHES_FILE=$5 BUILD_PIO=0
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
CHUNK_INDEX=0 CHUNK_INDEX=0
CHUNKS_CNT=1 CHUNKS_CNT=1
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ] && [ "$CHUNKS_CNT" -ge 2 ]; then elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ] && [ "$CHUNKS_CNT" -ge 2 ]; then
CHUNK_INDEX=$CHUNKS_CNT CHUNK_INDEX=$CHUNKS_CNT
elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
BUILD_PIO=1
fi fi
if [ -z "$BUILD_LOG" ] || [ "$BUILD_LOG" -le 0 ]; then if [ -z "$BUILD_LOG" ] || [ "$BUILD_LOG" -le 0 ]; then
@ -72,36 +72,54 @@ fi
#git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1 #git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1
SCRIPTS_DIR="./.github/scripts" SCRIPTS_DIR="./.github/scripts"
source "${SCRIPTS_DIR}/install-arduino-cli.sh" if [ "$BUILD_PIO" -eq 0 ]; then
source "${SCRIPTS_DIR}/install-arduino-core-esp32.sh" source ${SCRIPTS_DIR}/install-arduino-cli.sh
source ${SCRIPTS_DIR}/install-arduino-core-esp32.sh
SKETCHES_ESP32=( SKETCHES_ESP32="\
"$ARDUINO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" $ARDUINO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino\
"$ARDUINO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino" $ARDUINO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino\
"$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino" $ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino\
"$ARDUINO_ESP32_PATH/libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino" $ARDUINO_ESP32_PATH/libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino\
) "
#create sizes_file #create sizes_file
sizes_file="$GITHUB_WORKSPACE/cli_compile_$CHUNK_INDEX.json" sizes_file="$GITHUB_WORKSPACE/cli_compile_$CHUNK_INDEX.json"
if [ "$BUILD_LOG" -eq 1 ]; then if [ "$BUILD_LOG" -eq 1 ]; then
#create sizes_file and echo start of JSON array with "boards" key #create sizes_file and echo start of JSON array with "boards" key
echo "{\"boards\": [" > "$sizes_file" echo "{\"boards\": [" > $sizes_file
fi fi
#build sketches for different targets #build sketches for different targets
build "esp32c5" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" build "esp32s3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32p4" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" build "esp32s2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32s3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" build "esp32c3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32s2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" build "esp32c6" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32c3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" build "esp32h2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32c6" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" build "esp32" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32h2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
build "esp32" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" if [ "$BUILD_LOG" -eq 1 ]; then
#remove last comma from the last JSON object
if [ "$BUILD_LOG" -eq 1 ]; then sed -i '$ s/,$//' "$sizes_file"
#remove last comma from the last JSON object #echo end of JSON array
sed -i '$ s/,$//' "$sizes_file" echo "]}" >> $sizes_file
#echo end of JSON array fi
echo "]}" >> "$sizes_file" else
source ${SCRIPTS_DIR}/install-platformio-esp32.sh
# PlatformIO ESP32 Test
BOARD="esp32dev"
OPTIONS="board_build.partitions = huge_app.csv"
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
# Basic sanity testing for other series
for board in "esp32-c3-devkitm-1" "esp32-s2-saola-1" "esp32-s3-devkitc-1"
do
python -m platformio ci --board "$board" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient" --project-option="board_build.partitions = huge_app.csv"
done
#build_pio_sketches "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries"
fi fi

View file

@ -1,65 +1,52 @@
#!/bin/bash #!/bin/bash
# Disable shellcheck warning about using 'cat' to read a file.
# Disable shellcheck warning about using individual redirections for each command.
# Disable shellcheck warning about $? uses.
# shellcheck disable=SC2002,SC2129,SC2181,SC2319
if [ ! "$GITHUB_EVENT_NAME" == "release" ]; then if [ ! $GITHUB_EVENT_NAME == "release" ]; then
echo "Wrong event '$GITHUB_EVENT_NAME'!" echo "Wrong event '$GITHUB_EVENT_NAME'!"
exit 1 exit 1
fi fi
EVENT_JSON=$(cat "$GITHUB_EVENT_PATH") EVENT_JSON=`cat $GITHUB_EVENT_PATH`
action=$(echo "$EVENT_JSON" | jq -r '.action') action=`echo $EVENT_JSON | jq -r '.action'`
if [ ! "$action" == "published" ]; then if [ ! $action == "published" ]; then
echo "Wrong action '$action'. Exiting now..." echo "Wrong action '$action'. Exiting now..."
exit 0 exit 0
fi fi
draft=$(echo "$EVENT_JSON" | jq -r '.release.draft') draft=`echo $EVENT_JSON | jq -r '.release.draft'`
if [ "$draft" == "true" ]; then if [ $draft == "true" ]; then
echo "It's a draft release. Exiting now..." echo "It's a draft release. Exiting now..."
exit 0 exit 0
fi fi
RELEASE_PRE=$(echo "$EVENT_JSON" | jq -r '.release.prerelease') RELEASE_PRE=`echo $EVENT_JSON | jq -r '.release.prerelease'`
RELEASE_TAG=$(echo "$EVENT_JSON" | jq -r '.release.tag_name') RELEASE_TAG=`echo $EVENT_JSON | jq -r '.release.tag_name'`
RELEASE_BRANCH=$(echo "$EVENT_JSON" | jq -r '.release.target_commitish') RELEASE_BRANCH=`echo $EVENT_JSON | jq -r '.release.target_commitish'`
RELEASE_ID=$(echo "$EVENT_JSON" | jq -r '.release.id') RELEASE_ID=`echo $EVENT_JSON | jq -r '.release.id'`
SCRIPTS_DIR="./.github/scripts"
OUTPUT_DIR="$GITHUB_WORKSPACE/build" OUTPUT_DIR="$GITHUB_WORKSPACE/build"
PACKAGE_NAME="esp32-$RELEASE_TAG" PACKAGE_NAME="esp32-$RELEASE_TAG"
PACKAGE_JSON_MERGE="$GITHUB_WORKSPACE/.github/scripts/merge_packages.py" PACKAGE_JSON_MERGE="$GITHUB_WORKSPACE/.github/scripts/merge_packages.py"
PACKAGE_JSON_TEMPLATE="$GITHUB_WORKSPACE/package/package_esp32_index.template.json" PACKAGE_JSON_TEMPLATE="$GITHUB_WORKSPACE/package/package_esp32_index.template.json"
PACKAGE_JSON_DEV="package_esp32_dev_index.json" PACKAGE_JSON_DEV="package_esp32_dev_index.json"
PACKAGE_JSON_REL="package_esp32_index.json" PACKAGE_JSON_REL="package_esp32_index.json"
PACKAGE_JSON_DEV_CN="package_esp32_dev_index_cn.json"
PACKAGE_JSON_REL_CN="package_esp32_index_cn.json"
echo "Event: $GITHUB_EVENT_NAME, Repo: $GITHUB_REPOSITORY, Path: $GITHUB_WORKSPACE, Ref: $GITHUB_REF" echo "Event: $GITHUB_EVENT_NAME, Repo: $GITHUB_REPOSITORY, Path: $GITHUB_WORKSPACE, Ref: $GITHUB_REF"
echo "Action: $action, Branch: $RELEASE_BRANCH, ID: $RELEASE_ID" echo "Action: $action, Branch: $RELEASE_BRANCH, ID: $RELEASE_ID"
echo "Tag: $RELEASE_TAG, Draft: $draft, Pre-Release: $RELEASE_PRE" echo "Tag: $RELEASE_TAG, Draft: $draft, Pre-Release: $RELEASE_PRE"
# Try extracting something like a JSON with a "boards" array/element and "vendor" fields # Try extracting something like a JSON with a "boards" array/element and "vendor" fields
BOARDS=$(echo "$RELEASE_BODY" | grep -Pzo '(?s){.*}' | jq -r '.boards[]? // .boards? // empty' | xargs echo -n 2>/dev/null) BOARDS=`echo $RELEASE_BODY | grep -Pzo '(?s){.*}' | jq -r '.boards[]? // .boards? // empty' | xargs echo -n 2>/dev/null`
VENDOR=$(echo "$RELEASE_BODY" | grep -Pzo '(?s){.*}' | jq -r '.vendor? // empty' | xargs echo -n 2>/dev/null) VENDOR=`echo $RELEASE_BODY | grep -Pzo '(?s){.*}' | jq -r '.vendor? // empty' | xargs echo -n 2>/dev/null`
if ! [ -z "${BOARDS}" ]; then echo "Releasing board(s): $BOARDS" ; fi
if ! [ -z "${VENDOR}" ]; then echo "Setting packager: $VENDOR" ; fi
if [ -n "${BOARDS}" ]; then function get_file_size(){
echo "Releasing board(s): $BOARDS"
fi
if [ -n "${VENDOR}" ]; then
echo "Setting packager: $VENDOR"
fi
function get_file_size {
local file="$1" local file="$1"
if [[ "$OSTYPE" == "darwin"* ]]; then if [[ "$OSTYPE" == "darwin"* ]]; then
eval "$(stat -s "$file")" eval `stat -s "$file"`
local res="$?" local res="$?"
echo "${st_size:?}" echo "$st_size"
return $res return $res
else else
stat --printf="%s" "$file" stat --printf="%s" "$file"
@ -67,29 +54,23 @@ function get_file_size {
fi fi
} }
function git_upload_asset { function git_upload_asset(){
local name local name=$(basename "$1")
name=$(basename "$1")
# local mime=$(file -b --mime-type "$1") # local mime=$(file -b --mime-type "$1")
curl -k -X POST -sH "Authorization: token $GITHUB_TOKEN" -H "Content-Type: application/octet-stream" --data-binary @"$1" "https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$name" curl -k -X POST -sH "Authorization: token $GITHUB_TOKEN" -H "Content-Type: application/octet-stream" --data-binary @"$1" "https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$name"
} }
function git_safe_upload_asset { function git_safe_upload_asset(){
local file="$1" local file="$1"
local name local name=$(basename "$file")
local size local size=`get_file_size "$file"`
local upload_res local upload_res=`git_upload_asset "$file"`
if [ $? -ne 0 ]; then
name=$(basename "$file")
size=$(get_file_size "$file")
if ! upload_res=$(git_upload_asset "$file"); then
>&2 echo "ERROR: Failed to upload '$name' ($?)" >&2 echo "ERROR: Failed to upload '$name' ($?)"
return 1 return 1
fi fi
up_size=`echo "$upload_res" | jq -r '.size'`
up_size=$(echo "$upload_res" | jq -r '.size') if [ $up_size -ne $size ]; then
if [ "$up_size" -ne "$size" ]; then
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size" >&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
#git_delete_asset #git_delete_asset
return 1 return 1
@ -98,7 +79,7 @@ function git_safe_upload_asset {
return $? return $?
} }
function git_upload_to_pages { function git_upload_to_pages(){
local path=$1 local path=$1
local src=$2 local src=$2
@ -107,50 +88,41 @@ function git_upload_to_pages {
return 1 return 1
fi fi
local info local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
local type local type=`echo "$info" | jq -r '.type'`
local message local message=$(basename $path)
local sha="" local sha=""
local content="" local content=""
info=$(curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages") if [ $type == "file" ]; then
type=$(echo "$info" | jq -r '.type') sha=`echo "$info" | jq -r '.sha'`
message=$(basename "$path")
if [ "$type" == "file" ]; then
sha=$(echo "$info" | jq -r '.sha')
sha=",\"sha\":\"$sha\"" sha=",\"sha\":\"$sha\""
message="Updating $message" message="Updating $message"
elif [ ! "$type" == "null" ]; then elif [ ! $type == "null" ]; then
>&2 echo "Wrong type '$type'" >&2 echo "Wrong type '$type'"
return 1 return 1
else else
message="Creating $message" message="Creating $message"
fi fi
content=$(base64 -i "$src") content=`base64 -i "$src"`
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}" data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path" echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
} }
function git_safe_upload_to_pages { function git_safe_upload_to_pages(){
local path=$1 local path=$1
local file="$2" local file="$2"
local name local name=$(basename "$file")
local size local size=`get_file_size "$file"`
local upload_res local upload_res=`git_upload_to_pages "$path" "$file"`
if [ $? -ne 0 ]; then
name=$(basename "$file")
size=$(get_file_size "$file")
if ! upload_res=$(git_upload_to_pages "$path" "$file"); then
>&2 echo "ERROR: Failed to upload '$name' ($?)" >&2 echo "ERROR: Failed to upload '$name' ($?)"
return 1 return 1
fi fi
up_size=`echo "$upload_res" | jq -r '.content.size'`
up_size=$(echo "$upload_res" | jq -r '.content.size') if [ $up_size -ne $size ]; then
if [ "$up_size" -ne "$size" ]; then
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size" >&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
#git_delete_asset #git_delete_asset
return 1 return 1
@ -159,20 +131,15 @@ function git_safe_upload_to_pages {
return $? return $?
} }
function merge_package_json { function merge_package_json(){
local jsonLink=$1 local jsonLink=$1
local jsonOut=$2 local jsonOut=$2
local old_json=$OUTPUT_DIR/oldJson.json local old_json=$OUTPUT_DIR/oldJson.json
local merged_json=$OUTPUT_DIR/mergedJson.json local merged_json=$OUTPUT_DIR/mergedJson.json
local error_code=0
echo "Downloading previous JSON $jsonLink ..." echo "Downloading previous JSON $jsonLink ..."
curl -L -o "$old_json" "https://github.com/$GITHUB_REPOSITORY/releases/download/$jsonLink?access_token=$GITHUB_TOKEN" 2>/dev/null curl -L -o "$old_json" "https://github.com/$GITHUB_REPOSITORY/releases/download/$jsonLink?access_token=$GITHUB_TOKEN" 2>/dev/null
error_code=$? if [ $? -ne 0 ]; then echo "ERROR: Download Failed! $?"; exit 1; fi
if [ $error_code -ne 0 ]; then
echo "ERROR: Download Failed! $error_code"
exit 1
fi
echo "Creating new JSON ..." echo "Creating new JSON ..."
set +e set +e
@ -180,7 +147,7 @@ function merge_package_json {
set -e set -e
set -v set -v
if [ ! -s "$merged_json" ]; then if [ ! -s $merged_json ]; then
rm -f "$merged_json" rm -f "$merged_json"
echo "Nothing to merge" echo "Nothing to merge"
else else
@ -221,10 +188,9 @@ else
done done
# Copy only relevant variant files # Copy only relevant variant files
mkdir "$PKG_DIR/variants/" mkdir "$PKG_DIR/variants/"
board_list=$(cat "${PKG_DIR}"/boards.txt | grep "\.variant=" | cut -d= -f2) for variant in `cat ${PKG_DIR}/boards.txt | grep "\.variant=" | cut -d= -f2` ; do
while IFS= read -r variant; do
cp -Rf "$GITHUB_WORKSPACE/variants/${variant}" "$PKG_DIR/variants/" cp -Rf "$GITHUB_WORKSPACE/variants/${variant}" "$PKG_DIR/variants/"
done <<< "$board_list" done
fi fi
cp -f "$GITHUB_WORKSPACE/CMakeLists.txt" "$PKG_DIR/" cp -f "$GITHUB_WORKSPACE/CMakeLists.txt" "$PKG_DIR/"
cp -f "$GITHUB_WORKSPACE/idf_component.yml" "$PKG_DIR/" cp -f "$GITHUB_WORKSPACE/idf_component.yml" "$PKG_DIR/"
@ -241,7 +207,7 @@ cp -f "$GITHUB_WORKSPACE/tools/gen_insights_package.py" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/gen_insights_package.exe" "$PKG_DIR/tools/" cp -f "$GITHUB_WORKSPACE/tools/gen_insights_package.exe" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/" cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/ide-debug" "$PKG_DIR/tools/" cp -Rf "$GITHUB_WORKSPACE/tools/ide-debug" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/pioarduino-build.py" "$PKG_DIR/tools/" cp -f "$GITHUB_WORKSPACE/tools/platformio-build.py" "$PKG_DIR/tools/"
# Remove unnecessary files in the package folder # Remove unnecessary files in the package folder
echo "Cleaning up folders ..." echo "Cleaning up folders ..."
@ -253,8 +219,12 @@ find "$PKG_DIR" -name '*.git*' -type f -delete
## ##
RVTC_NAME="riscv32-esp-elf-gcc" RVTC_NAME="riscv32-esp-elf-gcc"
RVTC_NEW_NAME="esp-rv32" RVTC_NEW_NAME="esp-rv32"
X32TC_NAME="xtensa-esp-elf-gcc" X32TC_NAME="xtensa-esp32-elf-gcc"
X32TC_NEW_NAME="esp-x32" X32TC_NEW_NAME="esp-x32"
XS2TC_NAME="xtensa-esp32s2-elf-gcc"
XS2TC_NEW_NAME="esp-xs2"
XS3TC_NAME="xtensa-esp32s3-elf-gcc"
XS3TC_NEW_NAME="esp-xs3"
# Replace tools locations in platform.txt # Replace tools locations in platform.txt
echo "Generating platform.txt..." echo "Generating platform.txt..."
@ -263,40 +233,40 @@ sed "s/version=.*/version=$RELEASE_TAG/g" | \
sed 's/tools\.esp32-arduino-libs\.path\.windows=.*//g' | \ sed 's/tools\.esp32-arduino-libs\.path\.windows=.*//g' | \
sed 's/{runtime\.platform\.path}.tools.esp32-arduino-libs/\{runtime.tools.esp32-arduino-libs.path\}/g' | \ sed 's/{runtime\.platform\.path}.tools.esp32-arduino-libs/\{runtime.tools.esp32-arduino-libs.path\}/g' | \
sed 's/{runtime\.platform\.path}.tools.xtensa-esp-elf-gdb/\{runtime.tools.xtensa-esp-elf-gdb.path\}/g' | \ sed 's/{runtime\.platform\.path}.tools.xtensa-esp-elf-gdb/\{runtime.tools.xtensa-esp-elf-gdb.path\}/g' | \
sed "s/{runtime\.platform\.path}.tools.xtensa-esp-elf/\\{runtime.tools.$X32TC_NEW_NAME.path\\}/g" | \ sed "s/{runtime\.platform\.path}.tools.xtensa-esp32-elf/\\{runtime.tools.$X32TC_NEW_NAME.path\\}/g" | \
sed "s/{runtime\.platform\.path}.tools.xtensa-esp32s2-elf/\\{runtime.tools.$XS2TC_NEW_NAME.path\\}/g" | \
sed "s/{runtime\.platform\.path}.tools.xtensa-esp32s3-elf/\\{runtime.tools.$XS3TC_NEW_NAME.path\\}/g" | \
sed 's/{runtime\.platform\.path}.tools.riscv32-esp-elf-gdb/\{runtime.tools.riscv32-esp-elf-gdb.path\}/g' | \ sed 's/{runtime\.platform\.path}.tools.riscv32-esp-elf-gdb/\{runtime.tools.riscv32-esp-elf-gdb.path\}/g' | \
sed "s/{runtime\.platform\.path}.tools.riscv32-esp-elf/\\{runtime.tools.$RVTC_NEW_NAME.path\\}/g" | \ sed "s/{runtime\.platform\.path}.tools.riscv32-esp-elf/\\{runtime.tools.$RVTC_NEW_NAME.path\\}/g" | \
sed 's/{runtime\.platform\.path}.tools.esptool/\{runtime.tools.esptool_py.path\}/g' | \ sed 's/{runtime\.platform\.path}.tools.esptool/\{runtime.tools.esptool_py.path\}/g' | \
sed 's/{runtime\.platform\.path}.tools.openocd-esp32/\{runtime.tools.openocd-esp32.path\}/g' > "$PKG_DIR/platform.txt" sed 's/{runtime\.platform\.path}.tools.openocd-esp32/\{runtime.tools.openocd-esp32.path\}/g' \
> "$PKG_DIR/platform.txt"
if [ -n "${VENDOR}" ]; then if ! [ -z ${VENDOR} ]; then
# Append vendor name to platform.txt to create a separate section # Append vendor name to platform.txt to create a separate section
sed -i "/^name=.*/s/$/ ($VENDOR)/" "$PKG_DIR/platform.txt" sed -i "/^name=.*/s/$/ ($VENDOR)/" "$PKG_DIR/platform.txt"
fi fi
# Add header with version information # Add header with version information
echo "Generating core_version.h ..." echo "Generating core_version.h ..."
ver_define=$(echo "$RELEASE_TAG" | tr "[:lower:].\055" "[:upper:]_") ver_define=`echo $RELEASE_TAG | tr "[:lower:].\055" "[:upper:]_"`
ver_hex=$(git -C "$GITHUB_WORKSPACE" rev-parse --short=8 HEAD 2>/dev/null) ver_hex=`git -C "$GITHUB_WORKSPACE" rev-parse --short=8 HEAD 2>/dev/null`
echo \#define ARDUINO_ESP32_GIT_VER 0x"$ver_hex" > "$PKG_DIR/cores/esp32/core_version.h" echo \#define ARDUINO_ESP32_GIT_VER 0x$ver_hex > "$PKG_DIR/cores/esp32/core_version.h"
echo \#define ARDUINO_ESP32_GIT_DESC "$(git -C "$GITHUB_WORKSPACE" describe --tags 2>/dev/null)" >> "$PKG_DIR/cores/esp32/core_version.h" echo \#define ARDUINO_ESP32_GIT_DESC `git -C "$GITHUB_WORKSPACE" describe --tags 2>/dev/null` >> "$PKG_DIR/cores/esp32/core_version.h"
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"
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 package folder
echo "Creating ZIP ..." echo "Creating ZIP ..."
pushd "$OUTPUT_DIR" >/dev/null pushd "$OUTPUT_DIR" >/dev/null
zip -qr "$PACKAGE_ZIP" "$PACKAGE_NAME" zip -qr "$PACKAGE_ZIP" "$PACKAGE_NAME"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then echo "ERROR: Failed to create $PACKAGE_ZIP ($?)"; exit 1; fi
echo "ERROR: Failed to create $PACKAGE_ZIP ($?)"
exit 1
fi
# Calculate SHA-256 # Calculate SHA-256
echo "Calculating SHA sum ..." echo "Calculating SHA sum ..."
PACKAGE_PATH="$OUTPUT_DIR/$PACKAGE_ZIP" PACKAGE_PATH="$OUTPUT_DIR/$PACKAGE_ZIP"
PACKAGE_SHA=$(shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' ') PACKAGE_SHA=`shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' '`
PACKAGE_SIZE=$(get_file_size "$PACKAGE_ZIP") PACKAGE_SIZE=`get_file_size "$PACKAGE_ZIP"`
popd >/dev/null popd >/dev/null
rm -rf "$PKG_DIR" rm -rf "$PKG_DIR"
echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA" echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA"
@ -304,7 +274,7 @@ echo
# Upload package to release page # Upload package to release page
echo "Uploading package to release page ..." echo "Uploading package to release page ..."
PACKAGE_URL=$(git_safe_upload_asset "$PACKAGE_PATH") PACKAGE_URL=`git_safe_upload_asset "$PACKAGE_PATH"`
echo "Package Uploaded" echo "Package Uploaded"
echo "Download URL: $PACKAGE_URL" echo "Download URL: $PACKAGE_URL"
echo echo
@ -312,9 +282,9 @@ echo
## ##
## TEMP WORKAROUND FOR RV32 LONG PATH ON WINDOWS ## TEMP WORKAROUND FOR RV32 LONG PATH ON WINDOWS
## ##
RVTC_VERSION=$(cat "$PACKAGE_JSON_TEMPLATE" | jq -r ".packages[0].platforms[0].toolsDependencies[] | select(.name == \"$RVTC_NAME\") | .version" | cut -d '_' -f 2) RVTC_VERSION=`cat $PACKAGE_JSON_TEMPLATE | jq -r ".packages[0].platforms[0].toolsDependencies[] | select(.name == \"$RVTC_NAME\") | .version" | cut -d '_' -f 2`
# RVTC_VERSION=`date -j -f '%Y%m%d' "$RVTC_VERSION" '+%y%m'` # MacOS # RVTC_VERSION=`date -j -f '%Y%m%d' "$RVTC_VERSION" '+%y%m'` # MacOS
RVTC_VERSION=$(date -d "$RVTC_VERSION" '+%y%m') RVTC_VERSION=`date -d "$RVTC_VERSION" '+%y%m'`
rvtc_jq_arg="\ rvtc_jq_arg="\
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$RVTC_NAME\")).version = \"$RVTC_VERSION\" |\ (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$RVTC_NAME\")).version = \"$RVTC_VERSION\" |\
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$RVTC_NAME\")).name = \"$RVTC_NEW_NAME\" |\ (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$RVTC_NAME\")).name = \"$RVTC_NEW_NAME\" |\
@ -323,7 +293,15 @@ rvtc_jq_arg="\
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$X32TC_NAME\")).version = \"$RVTC_VERSION\" |\ (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$X32TC_NAME\")).version = \"$RVTC_VERSION\" |\
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\" |\ (.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\" |\
(.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).version = \"$RVTC_VERSION\" |\ (.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).version = \"$RVTC_VERSION\" |\
(.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\"" (.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\" |\
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS2TC_NAME\")).version = \"$RVTC_VERSION\" |\
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS2TC_NAME\")).name = \"$XS2TC_NEW_NAME\" |\
(.packages[0].tools[] | select(.name==\"$XS2TC_NAME\")).version = \"$RVTC_VERSION\" |\
(.packages[0].tools[] | select(.name==\"$XS2TC_NAME\")).name = \"$XS2TC_NEW_NAME\" |\
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS3TC_NAME\")).version = \"$RVTC_VERSION\" |\
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$XS3TC_NAME\")).name = \"$XS3TC_NEW_NAME\" |\
(.packages[0].tools[] | select(.name==\"$XS3TC_NAME\")).version = \"$RVTC_VERSION\" |\
(.packages[0].tools[] | select(.name==\"$XS3TC_NAME\")).name = \"$XS3TC_NEW_NAME\""
cat "$PACKAGE_JSON_TEMPLATE" | jq "$rvtc_jq_arg" > "$OUTPUT_DIR/package-rvfix.json" cat "$PACKAGE_JSON_TEMPLATE" | jq "$rvtc_jq_arg" > "$OUTPUT_DIR/package-rvfix.json"
PACKAGE_JSON_TEMPLATE="$OUTPUT_DIR/package-rvfix.json" PACKAGE_JSON_TEMPLATE="$OUTPUT_DIR/package-rvfix.json"
@ -339,26 +317,17 @@ jq_arg=".packages[0].platforms[0].version = \"$RELEASE_TAG\" | \
.packages[0].platforms[0].checksum = \"SHA-256:$PACKAGE_SHA\"" .packages[0].platforms[0].checksum = \"SHA-256:$PACKAGE_SHA\""
# Generate package JSONs # Generate package JSONs
echo "Generating $PACKAGE_JSON_DEV ..." echo "Genarating $PACKAGE_JSON_DEV ..."
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV" cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
# On MacOS the sed command won't skip the first match. Use gsed instead.
sed '0,/github\.com\//!s|github\.com/|dl.espressif.cn/github_assets/|g' "$OUTPUT_DIR/$PACKAGE_JSON_DEV" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN"
python "$SCRIPTS_DIR/release_append_cn.py" "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN"
if [ "$RELEASE_PRE" == "false" ]; then if [ "$RELEASE_PRE" == "false" ]; then
echo "Generating $PACKAGE_JSON_REL ..." echo "Genarating $PACKAGE_JSON_REL ..."
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_REL" cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_REL"
# On MacOS the sed command won't skip the first match. Use gsed instead.
sed '0,/github\.com\//!s|github\.com/|dl.espressif.cn/github_assets/|g' "$OUTPUT_DIR/$PACKAGE_JSON_REL" > "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN"
python "$SCRIPTS_DIR/release_append_cn.py" "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN"
fi fi
# Figure out the last release or pre-release # Figure out the last release or pre-release
echo "Getting previous releases ..." echo "Getting previous releases ..."
releasesJson=$(curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null) releasesJson=`curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null`
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi
echo "ERROR: Get Releases Failed! ($?)"
exit 1
fi
set +e set +e
prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name") prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
@ -378,17 +347,15 @@ echo "Previous (any)release: $prev_any_release"
echo echo
# Merge package JSONs with previous releases # Merge package JSONs with previous releases
if [ -n "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
echo "Merging with JSON from $prev_any_release ..." echo "Merging with JSON from $prev_any_release ..."
merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV" merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV_CN" "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN"
fi fi
if [ "$RELEASE_PRE" == "false" ]; then if [ "$RELEASE_PRE" == "false" ]; then
if [ -n "$prev_release" ] && [ "$prev_release" != "null" ]; then if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then
echo "Merging with JSON from $prev_release ..." echo "Merging with JSON from $prev_release ..."
merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL" merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"
merge_package_json "$prev_release/$PACKAGE_JSON_REL_CN" "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN"
fi fi
fi fi
@ -396,32 +363,21 @@ fi
echo "Installing arduino-cli ..." echo "Installing arduino-cli ..."
export PATH="/home/runner/bin:$PATH" export PATH="/home/runner/bin:$PATH"
source "${SCRIPTS_DIR}/install-arduino-cli.sh" source ./.github/scripts/install-arduino-cli.sh
# For the Chinese mirror, we can't test the package JSONs as the Chinese mirror might not be updated yet.
echo "Testing $PACKAGE_JSON_DEV install ..." echo "Testing $PACKAGE_JSON_DEV install ..."
echo "Installing esp32 ..." echo "Installing esp32 ..."
arduino-cli core install esp32:esp32 --additional-urls "file://$OUTPUT_DIR/$PACKAGE_JSON_DEV" arduino-cli core install esp32:esp32 --additional-urls "file://$OUTPUT_DIR/$PACKAGE_JSON_DEV"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then echo "ERROR: Failed to install esp32 ($?)"; exit 1; fi
echo "ERROR: Failed to install esp32 ($?)"
exit 1
fi
echo "Compiling example ..." echo "Compiling example ..."
arduino-cli compile --fqbn esp32:esp32:esp32 "$GITHUB_WORKSPACE"/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino arduino-cli compile --fqbn esp32:esp32:esp32 $GITHUB_WORKSPACE/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then echo "ERROR: Failed to compile example ($?)"; exit 1; fi
echo "ERROR: Failed to compile example ($?)"
exit 1
fi
echo "Uninstalling esp32 ..." echo "Uninstalling esp32 ..."
arduino-cli core uninstall esp32:esp32 arduino-cli core uninstall esp32:esp32
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then echo "ERROR: Failed to uninstall esp32 ($?)"; exit 1; fi
echo "ERROR: Failed to uninstall esp32 ($?)"
exit 1
fi
echo "Test successful!" echo "Test successful!"
@ -430,24 +386,15 @@ if [ "$RELEASE_PRE" == "false" ]; then
echo "Installing esp32 ..." echo "Installing esp32 ..."
arduino-cli core install esp32:esp32 --additional-urls "file://$OUTPUT_DIR/$PACKAGE_JSON_REL" arduino-cli core install esp32:esp32 --additional-urls "file://$OUTPUT_DIR/$PACKAGE_JSON_REL"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then echo "ERROR: Failed to install esp32 ($?)"; exit 1; fi
echo "ERROR: Failed to install esp32 ($?)"
exit 1
fi
echo "Compiling example ..." echo "Compiling example ..."
arduino-cli compile --fqbn esp32:esp32:esp32 "$GITHUB_WORKSPACE"/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino arduino-cli compile --fqbn esp32:esp32:esp32 $GITHUB_WORKSPACE/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then echo "ERROR: Failed to compile example ($?)"; exit 1; fi
echo "ERROR: Failed to compile example ($?)"
exit 1
fi
echo "Uninstalling esp32 ..." echo "Uninstalling esp32 ..."
arduino-cli core uninstall esp32:esp32 arduino-cli core uninstall esp32:esp32
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then echo "ERROR: Failed to uninstall esp32 ($?)"; exit 1; fi
echo "ERROR: Failed to uninstall esp32 ($?)"
exit 1
fi
echo "Test successful!" echo "Test successful!"
fi fi
@ -455,17 +402,13 @@ fi
# Upload package JSONs # Upload package JSONs
echo "Uploading $PACKAGE_JSON_DEV ..." echo "Uploading $PACKAGE_JSON_DEV ..."
echo "Download URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV")" echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
echo "Pages URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV")" echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
echo "Download CN URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN")"
echo "Pages CN URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_DEV_CN" "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN")"
echo echo
if [ "$RELEASE_PRE" == "false" ]; then if [ "$RELEASE_PRE" == "false" ]; then
echo "Uploading $PACKAGE_JSON_REL ..." echo "Uploading $PACKAGE_JSON_REL ..."
echo "Download URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL")" echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL"`
echo "Pages URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL")" echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"`
echo "Download CN URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN")"
echo "Pages CN URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_REL_CN" "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN")"
echo echo
fi fi

View file

@ -1,57 +0,0 @@
#!/usr/bin/env python3
# Arduino IDE provides by default a package file for the ESP32. This causes version conflicts
# when the user tries to use the JSON file with the Chinese mirrors.
#
# The downside is that the Arduino IDE will always warn the user that updates are available as it
# will consider the version from the Chinese mirrors as a pre-release version.
#
# This script is used to append "-cn" to all versions in the package_esp32_index_cn.json file so that
# the user can select the Chinese mirrors without conflicts.
#
# If Arduino ever stops providing the package_esp32_index.json file by default,
# this script can be removed and the tags reverted.
import json
def append_cn_to_versions(obj):
if isinstance(obj, dict):
# Skip tools that are not from the esp32 package
packager = obj.get("packager")
if packager is not None and packager != "esp32":
return
for key, value in obj.items():
if key == "version" and isinstance(value, str):
if not value.endswith("-cn"):
obj[key] = value + "-cn"
else:
append_cn_to_versions(value)
elif isinstance(obj, list):
for item in obj:
append_cn_to_versions(item)
def process_json_file(input_path, output_path=None):
with open(input_path, "r", encoding="utf-8") as f:
data = json.load(f)
append_cn_to_versions(data)
if output_path is None:
output_path = input_path
with open(output_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
print(f"Updated JSON written to {output_path}")
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("Usage: python release_append_cn.py input.json [output.json]")
else:
input_file = sys.argv[1]
output_file = sys.argv[2] if len(sys.argv) > 2 else None
process_json_file(input_file, output_file)

View file

@ -4,81 +4,80 @@ build_all=false
chunks_count=0 chunks_count=0
if [[ $CORE_CHANGED == 'true' ]] || [[ $IS_PR != 'true' ]]; then if [[ $CORE_CHANGED == 'true' ]] || [[ $IS_PR != 'true' ]]; then
echo "Core files changed or not a PR. Building all." echo "Core files changed or not a PR. Building all."
build_all=true build_all=true
chunks_count=$MAX_CHUNKS chunks_count=$MAX_CHUNKS
elif [[ $LIB_CHANGED == 'true' ]]; then elif [[ $LIB_CHANGED == 'true' ]]; then
echo "Libraries changed. Building only affected sketches." echo "Libraries changed. Building only affected sketches."
if [[ $NETWORKING_CHANGED == 'true' ]]; then if [[ $NETWORKING_CHANGED == 'true' ]]; then
echo "Networking libraries changed. Building networking related sketches." echo "Networking libraries changed. Building networking related sketches."
networking_sketches="$(find libraries/WiFi -name '*.ino') " networking_sketches="$(find libraries/WiFi -name *.ino) "
networking_sketches+="$(find libraries/Ethernet -name '*.ino') " networking_sketches+="$(find libraries/Ethernet -name *.ino) "
networking_sketches+="$(find libraries/PPP -name '*.ino') " networking_sketches+="$(find libraries/PPP -name *.ino) "
networking_sketches+="$(find libraries/NetworkClientSecure -name '*.ino') " networking_sketches+="$(find libraries/NetworkClientSecure -name *.ino) "
networking_sketches+="$(find libraries/WebServer -name '*.ino') " networking_sketches+="$(find libraries/WebServer -name *.ino) "
fi fi
if [[ $FS_CHANGED == 'true' ]]; then if [[ $FS_CHANGED == 'true' ]]; then
echo "FS libraries changed. Building FS related sketches." echo "FS libraries changed. Building FS related sketches."
fs_sketches="$(find libraries/SD -name '*.ino') " fs_sketches="$(find libraries/SD -name *.ino) "
fs_sketches+="$(find libraries/SD_MMC -name '*.ino') " fs_sketches+="$(find libraries/SD_MMC -name *.ino) "
fs_sketches+="$(find libraries/SPIFFS -name '*.ino') " fs_sketches+="$(find libraries/SPIFFS -name *.ino) "
fs_sketches+="$(find libraries/LittleFS -name '*.ino') " fs_sketches+="$(find libraries/LittleFS -name *.ino) "
fs_sketches+="$(find libraries/FFat -name '*.ino') " fs_sketches+="$(find libraries/FFat -name *.ino) "
fi fi
sketches="$networking_sketches $fs_sketches" sketches="$networking_sketches $fs_sketches"
for file in $LIB_FILES; do for file in $LIB_FILES; do
lib=$(echo "$file" | awk -F "/" '{print $1"/"$2}') if [[ $file == *.ino ]]; then
if [[ "$file" == *.ino ]]; then # If file ends with .ino, add it to the list of sketches
# If file ends with .ino, add it to the list of sketches echo "Sketch found: $file"
echo "Sketch found: $file" sketches+="$file "
sketches+="$file " elif [[ $(basename $(dirname $file)) == "src" ]]; then
elif [[ "$file" == "$lib/src/"* ]]; then # If file is in a src directory, find all sketches in the parent/examples directory
# If file is inside the src directory, find all sketches in the lib/examples directory echo "Library src file found: $file"
echo "Library src file found: $file" lib=$(dirname $(dirname $file))
if [[ -d $lib/examples ]]; then if [[ -d $lib/examples ]]; then
lib_sketches=$(find "$lib"/examples -name '*.ino') lib_sketches=$(find $lib/examples -name *.ino)
sketches+="$lib_sketches " sketches+="$lib_sketches "
echo "Library sketches: $lib_sketches" echo "Library sketches: $lib_sketches"
fi fi
else else
# If file is in a example folder but it is not a sketch, find all sketches in the current directory # If file is in a example folder but it is not a sketch, find all sketches in the current directory
echo "File in example folder found: $file" echo "File in example folder found: $file"
sketch=$(find "$(dirname "$file")" -name '*.ino') sketch=$(find $(dirname $file) -name *.ino)
sketches+="$sketch " sketches+="$sketch "
echo "Sketch in example folder: $sketch" echo "Sketch in example folder: $sketch"
fi fi
echo "" echo ""
done done
fi fi
if [[ -n $sketches ]]; then if [[ -n $sketches ]]; then
# Remove duplicates # Remove duplicates
sketches=$(echo "$sketches" | tr ' ' '\n' | sort | uniq) sketches=$(echo $sketches | tr ' ' '\n' | sort | uniq)
for sketch in $sketches; do for sketch in $sketches; do
echo "$sketch" >> sketches_found.txt echo $sketch >> sketches_found.txt
chunks_count=$((chunks_count+1)) chunks_count=$((chunks_count+1))
done done
echo "Number of sketches found: $chunks_count" echo "Number of sketches found: $chunks_count"
echo "Sketches:" echo "Sketches:"
echo "$sketches" echo "$sketches"
if [[ $chunks_count -gt $MAX_CHUNKS ]]; then if [[ $chunks_count -gt $MAX_CHUNKS ]]; then
echo "More sketches than the allowed number of chunks found. Limiting to $MAX_CHUNKS chunks." echo "More sketches than the allowed number of chunks found. Limiting to $MAX_CHUNKS chunks."
chunks_count=$MAX_CHUNKS chunks_count=$MAX_CHUNKS
fi fi
fi fi
chunks='["0"' chunks='["0"'
for i in $(seq 1 $(( chunks_count - 1 )) ); do for i in $(seq 1 $(( $chunks_count - 1 )) ); do
chunks+=",\"$i\"" chunks+=",\"$i\""
done done
chunks+="]" chunks+="]"
{ echo "build_all=$build_all" >> $GITHUB_OUTPUT
echo "build_all=$build_all" echo "build_libraries=$BUILD_LIBRARIES" >> $GITHUB_OUTPUT
echo "build_libraries=$BUILD_LIBRARIES" echo "build_static_sketches=$BUILD_STATIC_SKETCHES" >> $GITHUB_OUTPUT
echo "build_static_sketches=$BUILD_STATIC_SKETCHES" echo "build_idf=$BUILD_IDF" >> $GITHUB_OUTPUT
echo "build_idf=$BUILD_IDF" echo "build_platformio=$BUILD_PLATFORMIO" >> $GITHUB_OUTPUT
echo "chunk_count=$chunks_count" echo "chunk_count=$chunks_count" >> $GITHUB_OUTPUT
echo "chunks=$chunks" echo "chunks=$chunks" >> $GITHUB_OUTPUT
} >> "$GITHUB_OUTPUT"

View file

@ -1,60 +1,7 @@
#!/bin/bash #!/bin/bash
if [ -d "$ARDUINO_ESP32_PATH/tools/esp32-arduino-libs" ]; then function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [extra-options]
SDKCONFIG_DIR="$ARDUINO_ESP32_PATH/tools/esp32-arduino-libs" while [ ! -z "$1" ]; do
elif [ -d "$GITHUB_WORKSPACE/tools/esp32-arduino-libs" ]; then
SDKCONFIG_DIR="$GITHUB_WORKSPACE/tools/esp32-arduino-libs"
else
SDKCONFIG_DIR="tools/esp32-arduino-libs"
fi
function check_requirements { # check_requirements <sketchdir> <sdkconfig_path>
local sketchdir=$1
local sdkconfig_path=$2
local has_requirements=1
local requirements
local requirements_or
if [ ! -f "$sdkconfig_path" ] || [ ! -f "$sketchdir/ci.json" ]; then
echo "WARNING: sdkconfig or ci.json not found. Assuming requirements are met." 1>&2
# Return 1 on error to force the sketch to be built and fail. This way the
# CI will fail and the user will know that the sketch has a problem.
else
# Check if the sketch requires any configuration options (AND)
requirements=$(jq -r '.requires[]? // empty' "$sketchdir/ci.json")
if [[ "$requirements" != "null" && "$requirements" != "" ]]; then
for requirement in $requirements; do
requirement=$(echo "$requirement" | xargs)
found_line=$(grep -E "^$requirement" "$sdkconfig_path")
if [[ "$found_line" == "" ]]; then
has_requirements=0
fi
done
fi
# Check if the sketch requires any configuration options (OR)
requirements_or=$(jq -r '.requires_any[]? // empty' "$sketchdir/ci.json")
if [[ "$requirements_or" != "null" && "$requirements_or" != "" ]]; then
local found=false
for requirement in $requirements_or; do
requirement=$(echo "$requirement" | xargs)
found_line=$(grep -E "^$requirement" "$sdkconfig_path")
if [[ "$found_line" != "" ]]; then
found=true
break
fi
done
if [[ "$found" == "false" ]]; then
has_requirements=0
fi
fi
fi
echo $has_requirements
}
function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [extra-options]
while [ -n "$1" ]; do
case "$1" in case "$1" in
-ai ) -ai )
shift shift
@ -88,10 +35,6 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
shift shift
log_compilation=$1 log_compilation=$1
;; ;;
-d )
shift
debug_level="DebugLevel=$1"
;;
* ) * )
break break
;; ;;
@ -99,10 +42,10 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
shift shift
done done
xtra_opts=("$@") xtra_opts=$*
len=0 len=0
if [ -z "$sketchdir" ]; then if [ -z $sketchdir ]; then
echo "ERROR: Sketch directory not provided" echo "ERROR: Sketch directory not provided"
echo "$USAGE" echo "$USAGE"
exit 1 exit 1
@ -110,8 +53,8 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
# No FQBN was passed, try to get it from other options # No FQBN was passed, try to get it from other options
if [ -z "$fqbn" ]; then if [ -z $fqbn ]; then
if [ -z "$target" ]; then if [ -z $target ]; then
echo "ERROR: Unspecified chip" echo "ERROR: Unspecified chip"
echo "$USAGE" echo "$USAGE"
exit 1 exit 1
@ -122,83 +65,52 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
# precedence. Note that the following logic also falls to the default # precedence. Note that the following logic also falls to the default
# parameters if no arguments were passed and no file was found. # parameters if no arguments were passed and no file was found.
if [ -z "$options" ] && [ -f "$sketchdir"/ci.json ]; then if [ -z $options ] && [ -f $sketchdir/ci.json ]; then
# The config file could contain multiple FQBNs for one chip. If # The config file could contain multiple FQBNs for one chip. If
# that's the case we build one time for every FQBN. # that's the case we build one time for every FQBN.
len=$(jq -r --arg target "$target" '.fqbn[$target] | length' "$sketchdir"/ci.json) len=`jq -r --arg target $target '.fqbn[$target] | length' $sketchdir/ci.json`
if [ "$len" -gt 0 ]; then if [ $len -gt 0 ]; then
fqbn=$(jq -r --arg target "$target" '.fqbn[$target] | sort' "$sketchdir"/ci.json) fqbn=`jq -r --arg target $target '.fqbn[$target] | sort' $sketchdir/ci.json`
fi fi
fi fi
if [ -n "$options" ] || [ "$len" -eq 0 ]; then if [ ! -z $options ] || [ $len -eq 0 ]; then
# Since we are passing options, we will end up with only one FQBN to # Since we are passing options, we will end up with only one FQBN to
# build. # build.
len=1 len=1
if [ -f "$sketchdir"/ci.json ]; then
fqbn_append=$(jq -r '.fqbn_append' "$sketchdir"/ci.json)
if [ "$fqbn_append" == "null" ]; then
fqbn_append=""
fi
fi
# Default FQBN options if none were passed in the command line. # Default FQBN options if none were passed in the command line.
# Replace any double commas with a single one and strip leading and
# trailing commas.
esp32_opts=$(echo "PSRAM=enabled,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') esp32_opts="PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio"
esp32s2_opts=$(echo "PSRAM=enabled,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') esp32s2_opts="PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio"
esp32s3_opts=$(echo "PSRAM=opi,USBMode=default,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') esp32s3_opts="PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=dio"
esp32c3_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') esp32c3_opts="PartitionScheme=huge_app,FlashMode=dio"
esp32c6_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') esp32c6_opts="PartitionScheme=huge_app,FlashMode=dio"
esp32h2_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g') esp32h2_opts="PartitionScheme=huge_app,FlashMode=dio"
esp32p4_opts=$(echo "PSRAM=enabled,USBMode=default,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
esp32c5_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
# Select the common part of the FQBN based on the target. The rest will be # Select the common part of the FQBN based on the target. The rest will be
# appended depending on the passed options. # appended depending on the passed options.
opt=""
case "$target" in case "$target" in
"esp32") "esp32")
[ -n "${options:-$esp32_opts}" ] && opt=":${options:-$esp32_opts}" fqbn="espressif:esp32:esp32:${options:-$esp32_opts}"
fqbn="espressif:esp32:esp32$opt"
;; ;;
"esp32s2") "esp32s2")
[ -n "${options:-$esp32s2_opts}" ] && opt=":${options:-$esp32s2_opts}" fqbn="espressif:esp32:esp32s2:${options:-$esp32s2_opts}"
fqbn="espressif:esp32:esp32s2$opt"
;; ;;
"esp32c3") "esp32c3")
[ -n "${options:-$esp32c3_opts}" ] && opt=":${options:-$esp32c3_opts}" fqbn="espressif:esp32:esp32c3:${options:-$esp32c3_opts}"
fqbn="espressif:esp32:esp32c3$opt"
;; ;;
"esp32s3") "esp32s3")
[ -n "${options:-$esp32s3_opts}" ] && opt=":${options:-$esp32s3_opts}" fqbn="espressif:esp32:esp32s3:${options:-$esp32s3_opts}"
fqbn="espressif:esp32:esp32s3$opt"
;; ;;
"esp32c6") "esp32c6")
[ -n "${options:-$esp32c6_opts}" ] && opt=":${options:-$esp32c6_opts}" fqbn="espressif:esp32:esp32c6:${options:-$esp32c6_opts}"
fqbn="espressif:esp32:esp32c6$opt"
;; ;;
"esp32h2") "esp32h2")
[ -n "${options:-$esp32h2_opts}" ] && opt=":${options:-$esp32h2_opts}" fqbn="espressif:esp32:esp32h2:${options:-$esp32h2_opts}"
fqbn="espressif:esp32:esp32h2$opt"
;;
"esp32p4")
[ -n "${options:-$esp32p4_opts}" ] && opt=":${options:-$esp32p4_opts}"
fqbn="espressif:esp32:esp32p4$opt"
;;
"esp32c5")
[ -n "${options:-$esp32c5_opts}" ] && opt=":${options:-$esp32c5_opts}"
fqbn="espressif:esp32:esp32c5$opt"
;;
*)
echo "ERROR: Invalid chip: $target"
exit 1
;; ;;
esac esac
@ -218,7 +130,7 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
exit 1 exit 1
fi fi
# The directory that will hold all the artifacts (the build directory) is # The directory that will hold all the artifcats (the build directory) is
# provided through: # provided through:
# 1. An env variable called ARDUINO_BUILD_DIR. # 1. An env variable called ARDUINO_BUILD_DIR.
# 2. Created at the sketch level as "build" in the case of a single # 2. Created at the sketch level as "build" in the case of a single
@ -226,79 +138,77 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
# 3. Created at the sketch level as "buildX" where X is the number # 3. Created at the sketch level as "buildX" where X is the number
# of configuration built in case of a multiconfiguration test. # of configuration built in case of a multiconfiguration test.
sketchname=$(basename "$sketchdir") sketchname=$(basename $sketchdir)
local has_requirements
if [ -f "$sketchdir"/ci.json ]; then # If the target is listed as false, skip the sketch. Otherwise, include it.
# If the target is listed as false, skip the sketch. Otherwise, include it. if [ -f $sketchdir/ci.json ]; then
is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json) is_target=$(jq -r --arg target $target '.targets[$target]' $sketchdir/ci.json)
if [[ "$is_target" == "false" ]]; then else
echo "Skipping $sketchname for target $target" is_target="true"
exit 0 fi
fi
has_requirements=$(check_requirements "$sketchdir" "$SDKCONFIG_DIR/$target/sdkconfig") if [[ "$is_target" == "false" ]]; then
if [ "$has_requirements" == "0" ]; then echo "Skipping $sketchname for target $target"
echo "Target $target does not meet the requirements for $sketchname. Skipping." exit 0
exit 0
fi
fi fi
ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp" ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp"
if [ -n "$ARDUINO_BUILD_DIR" ]; then if [ -n "$ARDUINO_BUILD_DIR" ]; then
build_dir="$ARDUINO_BUILD_DIR" build_dir="$ARDUINO_BUILD_DIR"
elif [ "$len" -eq 1 ]; then elif [ $len -eq 1 ]; then
# build_dir="$sketchdir/build" # build_dir="$sketchdir/build"
build_dir="$HOME/.arduino/tests/$target/$sketchname/build.tmp" build_dir="$HOME/.arduino/tests/$sketchname/build.tmp"
fi fi
output_file="$HOME/.arduino/cli_compile_output.txt" output_file="$HOME/.arduino/cli_compile_output.txt"
sizes_file="$GITHUB_WORKSPACE/cli_compile_$chunk_index.json" sizes_file="$GITHUB_WORKSPACE/cli_compile_$chunk_index.json"
mkdir -p "$ARDUINO_CACHE_DIR" mkdir -p "$ARDUINO_CACHE_DIR"
for i in $(seq 0 $((len - 1))); do for i in `seq 0 $(($len - 1))`
if [ "$len" -ne 1 ]; then do
# build_dir="$sketchdir/build$i" if [ $len -ne 1 ]; then
build_dir="$HOME/.arduino/tests/$target/$sketchname/build$i.tmp" # build_dir="$sketchdir/build$i"
build_dir="$HOME/.arduino/tests/$sketchname/build$i.tmp"
fi fi
rm -rf "$build_dir" rm -rf $build_dir
mkdir -p "$build_dir" mkdir -p $build_dir
currfqbn=$(echo "$fqbn" | jq -r --argjson i "$i" '.[$i]') currfqbn=`echo $fqbn | jq -r --argjson i $i '.[$i]'`
if [ -f "$ide_path/arduino-cli" ]; then if [ -f "$ide_path/arduino-cli" ]; then
echo "Building $sketchname with arduino-cli and FQBN=$currfqbn" echo "Building $sketchname with arduino-cli and FQBN=$currfqbn"
curroptions=$(echo "$currfqbn" | cut -d':' -f4) curroptions=`echo "$currfqbn" | cut -d':' -f4`
currfqbn=$(echo "$currfqbn" | cut -d':' -f1-3) currfqbn=`echo "$currfqbn" | cut -d':' -f1-3`
"$ide_path"/arduino-cli compile \ $ide_path/arduino-cli compile \
--fqbn "$currfqbn" \ --fqbn "$currfqbn" \
--board-options "$curroptions" \ --board-options "$curroptions" \
--warnings "all" \ --warnings "all" \
--build-property "compiler.warning_flags.all=-Wall -Werror=all -Wextra" \ --build-property "compiler.warning_flags.all=-Wall -Werror=all -Wextra" \
--build-cache-path "$ARDUINO_CACHE_DIR" \
--build-path "$build_dir" \ --build-path "$build_dir" \
"${xtra_opts[@]}" "${sketchdir}" \ $xtra_opts "${sketchdir}" \
2>&1 | tee "$output_file" > $output_file
exit_status=${PIPESTATUS[0]} exit_status=$?
if [ "$exit_status" -ne 0 ]; then if [ $exit_status -ne 0 ]; then
echo "ERROR: Compilation failed with error code $exit_status" echo "ERROR: Compilation failed with error code $exit_status"
exit "$exit_status" exit $exit_status
fi fi
if [ -n "$log_compilation" ]; then if [ $log_compilation ]; then
#Extract the program storage space and dynamic memory usage in bytes and percentage in separate variables from the output, just the value without the string #Extract the program storage space and dynamic memory usage in bytes and percentage in separate variables from the output, just the value without the string
flash_bytes=$(grep -oE 'Sketch uses ([0-9]+) bytes' "$output_file" | awk '{print $3}') flash_bytes=$(grep -oE 'Sketch uses ([0-9]+) bytes' $output_file | awk '{print $3}')
flash_percentage=$(grep -oE 'Sketch uses ([0-9]+) bytes \(([0-9]+)%\)' "$output_file" | awk '{print $5}' | tr -d '(%)') flash_percentage=$(grep -oE 'Sketch uses ([0-9]+) bytes \(([0-9]+)%\)' $output_file | awk '{print $5}' | tr -d '(%)')
ram_bytes=$(grep -oE 'Global variables use ([0-9]+) bytes' "$output_file" | awk '{print $4}') ram_bytes=$(grep -oE 'Global variables use ([0-9]+) bytes' $output_file | awk '{print $4}')
ram_percentage=$(grep -oE 'Global variables use ([0-9]+) bytes \(([0-9]+)%\)' "$output_file" | awk '{print $6}' | tr -d '(%)') ram_percentage=$(grep -oE 'Global variables use ([0-9]+) bytes \(([0-9]+)%\)' $output_file | awk '{print $6}' | tr -d '(%)')
# Extract the directory path excluding the filename # Extract the directory path excluding the filename
directory_path=$(dirname "$sketch") directory_path=$(dirname "$sketch")
# Define the constant part # Define the constant part
constant_part="/home/runner/Arduino/hardware/espressif/esp32/libraries/" constant_part="/home/runner/Arduino/hardware/espressif/esp32/libraries/"
# Extract the desired substring # Extract the desired substring using sed
lib_sketch_name="${directory_path#"$constant_part"}" lib_sketch_name=$(echo "$directory_path" | sed "s|$constant_part||")
#append json file where key is fqbn, sketch name, sizes -> extracted values #append json file where key is fqbn, sketch name, sizes -> extracted values
echo "{\"name\": \"$lib_sketch_name\", echo "{\"name\": \"$lib_sketch_name\",
\"sizes\": [{ \"sizes\": [{
@ -314,15 +224,15 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
echo "Building $sketchname with arduino-builder and FQBN=$currfqbn" echo "Building $sketchname with arduino-builder and FQBN=$currfqbn"
echo "Build path = $build_dir" echo "Build path = $build_dir"
"$ide_path"/arduino-builder -compile -logger=human -core-api-version=10810 \ $ide_path/arduino-builder -compile -logger=human -core-api-version=10810 \
-fqbn=\""$currfqbn"\" \ -fqbn=\"$currfqbn\" \
-warnings="all" \ -warnings="all" \
-tools "$ide_path/tools-builder" \ -tools "$ide_path/tools-builder" \
-hardware "$user_path/hardware" \ -hardware "$user_path/hardware" \
-libraries "$user_path/libraries" \ -libraries "$user_path/libraries" \
-build-cache "$ARDUINO_CACHE_DIR" \ -build-cache "$ARDUINO_CACHE_DIR" \
-build-path "$build_dir" \ -build-path "$build_dir" \
"${xtra_opts[@]}" "${sketchdir}/${sketchname}.ino" $xtra_opts "${sketchdir}/${sketchname}.ino"
exit_status=$? exit_status=$?
if [ $exit_status -ne 0 ]; then if [ $exit_status -ne 0 ]; then
@ -349,16 +259,14 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
unset options unset options
} }
function count_sketches { # count_sketches <path> [target] [file] [ignore-requirements] function count_sketches(){ # count_sketches <path> [target] [file]
local path=$1 local path=$1
local target=$2 local target=$2
local ignore_requirements=$3 local file=$3
local file=$4
local sketches
if [ $# -lt 1 ]; then if [ $# -lt 1 ]; then
echo "ERROR: Illegal number of parameters" echo "ERROR: Illegal number of parameters"
echo "USAGE: ${0} count <path> [target]" echo "USAGE: ${0} count <path> [target]"
fi fi
rm -rf sketches.txt rm -rf sketches.txt
@ -367,48 +275,40 @@ function count_sketches { # count_sketches <path> [target] [file] [ignore-requir
return 0 return 0
fi fi
if [ -f "$file" ]; then if [ -n "$file" ]; then
sketches=$(cat "$file") local sketches=$(cat $file)
else else
sketches=$(find "$path" -name '*.ino' | sort) local sketches=$(find $path -name *.ino | sort)
fi fi
local sketchnum=0 local sketchnum=0
for sketch in $sketches; do for sketch in $sketches; do
local sketchdir local sketchdir=$(dirname $sketch)
local sketchdirname local sketchdirname=$(basename $sketchdir)
local sketchname local sketchname=$(basename $sketch)
local has_requirements
sketchdir=$(dirname "$sketch")
sketchdirname=$(basename "$sketchdir")
sketchname=$(basename "$sketch")
if [[ "$sketchdirname.ino" != "$sketchname" ]]; then if [[ "$sketchdirname.ino" != "$sketchname" ]]; then
continue continue
elif [[ -n $target ]] && [[ -f $sketchdir/ci.json ]]; then elif [[ -n $target ]]; then
# If the target is listed as false, skip the sketch. Otherwise, include it. # If the target is listed as false, skip the sketch. Otherwise, include it.
is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json) if [ -f $sketchdir/ci.json ]; then
is_target=$(jq -r --arg target $target '.targets[$target]' $sketchdir/ci.json)
else
is_target="true"
fi
if [[ "$is_target" == "false" ]]; then if [[ "$is_target" == "false" ]]; then
continue continue
fi fi
if [ "$ignore_requirements" != "1" ]; then
has_requirements=$(check_requirements "$sketchdir" "$SDKCONFIG_DIR/$target/sdkconfig")
if [ "$has_requirements" == "0" ]; then
continue
fi
fi
fi fi
echo "$sketch" >> sketches.txt echo $sketch >> sketches.txt
sketchnum=$((sketchnum + 1)) sketchnum=$(($sketchnum + 1))
done done
return $sketchnum return $sketchnum
} }
function build_sketches { # build_sketches <ide_path> <user_path> <target> <path> <chunk> <total-chunks> [extra-options] function build_sketches(){ # build_sketches <ide_path> <user_path> <target> <path> <chunk> <total-chunks> [extra-options]
local args=()
while [ -n "$1" ]; do local args=""
while [ ! -z "$1" ]; do
case $1 in case $1 in
-ai ) -ai )
shift shift
@ -421,12 +321,12 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
-t ) -t )
shift shift
target=$1 target=$1
args+=("-t" "$target") args+=" -t $target"
;; ;;
-fqbn ) -fqbn )
shift shift
fqbn=$1 fqbn=$1
args+=("-fqbn" "$fqbn") args+=" -fqbn $fqbn"
;; ;;
-p ) -p )
shift shift
@ -448,11 +348,6 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
shift shift
sketches_file=$1 sketches_file=$1
;; ;;
-d )
shift
debug_level="$1"
args+=("-d" "$debug_level")
;;
* ) * )
break break
;; ;;
@ -460,10 +355,10 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
shift shift
done done
local xtra_opts=("$@") local xtra_opts=$*
if [ -z "$chunk_index" ] || [ -z "$chunk_max" ]; then if [ -z "$chunk_index" ] || [ -z "$chunk_max" ]; then
echo "ERROR: Invalid chunk parameters" echo "ERROR: Invalid chunk paramters"
echo "$USAGE" echo "$USAGE"
exit 1 exit 1
fi fi
@ -479,23 +374,20 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
set +e set +e
if [ -n "$sketches_file" ]; then if [ -n "$sketches_file" ]; then
count_sketches "$path" "$target" "0" "$sketches_file" count_sketches "$path" "$target" "$sketches_file"
local sketchcount=$? local sketchcount=$?
else else
count_sketches "$path" "$target" count_sketches "$path" "$target"
local sketchcount=$? local sketchcount=$?
fi fi
set -e set -e
local sketches local sketches=$(cat sketches.txt)
sketches=$(cat sketches.txt)
rm -rf sketches.txt rm -rf sketches.txt
local chunk_size local chunk_size=$(( $sketchcount / $chunk_max ))
local all_chunks local all_chunks=$(( $chunk_max * $chunk_size ))
chunk_size=$(( sketchcount / chunk_max ))
all_chunks=$(( chunk_max * chunk_size ))
if [ "$all_chunks" -lt "$sketchcount" ]; then if [ "$all_chunks" -lt "$sketchcount" ]; then
chunk_size=$(( chunk_size + 1 )) chunk_size=$(( $chunk_size + 1 ))
fi fi
local start_index=0 local start_index=0
@ -504,20 +396,19 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
start_index=$chunk_index start_index=$chunk_index
end_index=$sketchcount end_index=$sketchcount
else else
start_index=$(( chunk_index * chunk_size )) start_index=$(( $chunk_index * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then if [ "$sketchcount" -le "$start_index" ]; then
echo "No sketches to build for $target in this chunk" echo "No sketches to build for $target in this chunk"
return 0 return 0
fi fi
end_index=$(( $(( chunk_index + 1 )) * chunk_size )) end_index=$(( $(( $chunk_index + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then if [ "$end_index" -gt "$sketchcount" ]; then
end_index=$sketchcount end_index=$sketchcount
fi fi
fi fi
local start_num local start_num=$(( $start_index + 1 ))
start_num=$(( start_index + 1 ))
echo "Found $sketchcount Sketches for target '$target'"; echo "Found $sketchcount Sketches for target '$target'";
echo "Chunk Index : $chunk_index" echo "Chunk Index : $chunk_index"
echo "Chunk Count : $chunk_max" echo "Chunk Count : $chunk_max"
@ -525,50 +416,39 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
echo "Start Sketch: $start_num" echo "Start Sketch: $start_num"
echo "End Sketch : $end_index" echo "End Sketch : $end_index"
#if fqbn is not passed then set it to default for compilation log
if [ -z "$fqbn" ]; then
log_fqbn="espressif:esp32:$target"
else
log_fqbn=$fqbn
fi
sizes_file="$GITHUB_WORKSPACE/cli_compile_$chunk_index.json" sizes_file="$GITHUB_WORKSPACE/cli_compile_$chunk_index.json"
if [ -n "$log_compilation" ]; then if [ $log_compilation ]; then
#echo board,target and start of sketches to sizes_file json #echo board,target and start of sketches to sizes_file json
echo "{ \"board\": \"$log_fqbn\", echo "{ \"board\": \"$fqbn\",
\"target\": \"$target\", \"target\": \"$target\",
\"sketches\": [" >> "$sizes_file" \"sketches\": [" >> "$sizes_file"
fi fi
local sketchnum=0 local sketchnum=0
args+=("-ai" "$ide_path" "-au" "$user_path" "-i" "$chunk_index") args+=" -ai $ide_path -au $user_path -i $chunk_index"
if [ -n "$log_compilation" ]; then if [ $log_compilation ]; then
args+=("-l" "$log_compilation") args+=" -l $log_compilation"
fi fi
for sketch in $sketches; do for sketch in $sketches; do
local sketchdir local sketchdir=$(dirname $sketch)
local sketchdirname local sketchdirname=$(basename $sketchdir)
sketchnum=$(($sketchnum + 1))
sketchdir=$(dirname "$sketch")
sketchdirname=$(basename "$sketchdir")
sketchnum=$((sketchnum + 1))
if [ "$sketchnum" -le "$start_index" ] \ if [ "$sketchnum" -le "$start_index" ] \
|| [ "$sketchnum" -gt "$end_index" ]; then || [ "$sketchnum" -gt "$end_index" ]; then
continue continue
fi fi
echo "" echo ""
echo "Building Sketch Index $sketchnum - $sketchdirname" echo "Building Sketch Index $sketchnum - $sketchdirname"
build_sketch "${args[@]}" -s "$sketchdir" "${xtra_opts[@]}" build_sketch $args -s $sketchdir $xtra_opts
local result=$? local result=$?
if [ $result -ne 0 ]; then if [ $result -ne 0 ]; then
return $result return $result
fi fi
done done
if [ -n "$log_compilation" ]; then if [ $log_compilation ]; then
#remove last comma from json #remove last comma from json
if [ "$i" -eq $((len - 1)) ]; then if [ $i -eq $(($len - 1)) ]; then
sed -i '$ s/.$//' "$sizes_file" sed -i '$ s/.$//' "$sizes_file"
fi fi
#echo end of sketches sizes_file json #echo end of sketches sizes_file json
@ -583,28 +463,25 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
USAGE=" USAGE="
USAGE: ${0} [command] [options] USAGE: ${0} [command] [options]
Available commands: Available commands:
count: Count sketches. count: Count sketches.
build: Build a sketch. build: Build a sketch.
chunk_build: Build a chunk of sketches. chunk_build: Build a chunk of sketches.
check_requirements: Check if target meets sketch requirements.
" "
cmd=$1 cmd=$1
shift shift
if [ -z "$cmd" ]; then if [ -z $cmd ]; then
echo "ERROR: No command supplied" echo "ERROR: No command supplied"
echo "$USAGE" echo "$USAGE"
exit 2 exit 2
fi fi
case "$cmd" in case "$cmd" in
"count") count_sketches "$@" "count") count_sketches $*
;; ;;
"build") build_sketch "$@" "build") build_sketch $*
;; ;;
"chunk_build") build_sketches "$@" "chunk_build") build_sketches $*
;;
"check_requirements") check_requirements "$@"
;; ;;
*) *)
echo "ERROR: Unrecognized command" echo "ERROR: Unrecognized command"

View file

@ -3,14 +3,14 @@
USAGE=" USAGE="
USAGE: USAGE:
${0} -c -type <test_type> <chunk_build_opts> ${0} -c -type <test_type> <chunk_build_opts>
Example: ${0} -c -type validation -t esp32 -i 0 -m 15 Example: ${0} -c -type validation -t esp32 -i 0 -m 15
${0} -s sketch_name <build_opts> ${0} -s sketch_name <build_opts>
Example: ${0} -s hello_world -t esp32 Example: ${0} -s hello_world -t esp32
${0} -clean ${0} -clean
Remove build and test generated files Remove build and test generated files
" "
function clean { function clean(){
rm -rf tests/.pytest_cache rm -rf tests/.pytest_cache
find tests/ -type d -name 'build*' -exec rm -rf "{}" \+ find tests/ -type d -name 'build*' -exec rm -rf "{}" \+
find tests/ -type d -name '__pycache__' -exec rm -rf "{}" \+ find tests/ -type d -name '__pycache__' -exec rm -rf "{}" \+
@ -23,7 +23,7 @@ BUILD_CMD=""
chunk_build=0 chunk_build=0
while [ -n "$1" ]; do while [ ! -z "$1" ]; do
case $1 in case $1 in
-c ) -c )
chunk_build=1 chunk_build=1
@ -45,25 +45,25 @@ while [ -n "$1" ]; do
exit 0 exit 0
;; ;;
* ) * )
break break
;; ;;
esac esac
shift shift
done done
source "${SCRIPTS_DIR}/install-arduino-cli.sh" source ${SCRIPTS_DIR}/install-arduino-cli.sh
source "${SCRIPTS_DIR}/install-arduino-core-esp32.sh" source ${SCRIPTS_DIR}/install-arduino-core-esp32.sh
args=("-ai" "$ARDUINO_IDE_PATH" "-au" "$ARDUINO_USR_PATH") args="-ai $ARDUINO_IDE_PATH -au $ARDUINO_USR_PATH"
if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then
if [ -n "$sketch" ]; then if [ -n "$sketch" ]; then
tmp_sketch_path=$(find tests -name "$sketch".ino) tmp_sketch_path=$(find tests -name $sketch.ino)
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")") test_type=$(basename $(dirname $(dirname "$tmp_sketch_path")))
echo "Sketch $sketch test type: $test_type" echo "Sketch $sketch test type: $test_type"
test_folder="$PWD/tests/$test_type" test_folder="$PWD/tests/$test_type"
else else
test_folder="$PWD/tests" test_folder="$PWD/tests"
fi fi
else else
test_folder="$PWD/tests/$test_type" test_folder="$PWD/tests/$test_type"
@ -71,10 +71,11 @@ fi
if [ $chunk_build -eq 1 ]; then if [ $chunk_build -eq 1 ]; then
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh chunk_build" BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh chunk_build"
args+=("-p" "$test_folder" "-i" "0" "-m" "1") args+=" -p $test_folder -i 0 -m 1"
else else
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build" BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
args+=("-s" "$test_folder/$sketch") args+=" -s $test_folder/$sketch"
fi fi
${BUILD_CMD} "${args[@]}" "$@" ${BUILD_CMD} ${args} $*

View file

@ -1,28 +0,0 @@
#!/bin/bash
build_types="'validation'"
hw_types="'validation'"
wokwi_types="'validation'"
qemu_types="'validation'"
if [[ $IS_PR != 'true' ]] || [[ $PERFORMANCE_ENABLED == 'true' ]]; then
build_types+=",'performance'"
hw_types+=",'performance'"
#wokwi_types+=",'performance'"
#qemu_types+=",'performance'"
fi
targets="'esp32','esp32s2','esp32s3','esp32c3','esp32c6','esp32h2','esp32p4'"
mkdir -p info
echo "[$wokwi_types]" > info/wokwi_types.txt
echo "[$targets]" > info/targets.txt
{
echo "build-types=[$build_types]"
echo "hw-types=[$hw_types]"
echo "wokwi-types=[$wokwi_types]"
echo "qemu-types=[$qemu_types]"
echo "targets=[$targets]"
} >> "$GITHUB_OUTPUT"

View file

@ -1,132 +1,107 @@
#!/bin/bash #!/bin/bash
function run_test { function run_test() {
local target=$1 local target=$1
local sketch=$2 local sketch=$2
local options=$3 local options=$3
local erase_flash=$4 local erase_flash=$4
local sketchdir local sketchdir=$(dirname $sketch)
local sketchname local sketchname=$(basename $sketchdir)
local result=0 local result=0
local error=0 local error=0
local sdkconfig_path
local extra_args
local test_type
sketchdir=$(dirname "$sketch") # If the target or platform is listed as false, skip the sketch. Otherwise, include it.
sketchname=$(basename "$sketchdir") if [ -f $sketchdir/ci.json ]; then
test_type=$(basename "$(dirname "$sketchdir")") is_target=$(jq -r --arg target $target '.targets[$target]' $sketchdir/ci.json)
selected_platform=$(jq -r --arg platform $platform '.platforms[$platform]' $sketchdir/ci.json)
else
is_target="true"
selected_platform="true"
fi
if [ "$options" -eq 0 ] && [ -f "$sketchdir"/ci.json ]; then if [[ $is_target == "false" ]] || [[ $selected_platform == "false" ]]; then
len=$(jq -r --arg target "$target" '.fqbn[$target] | length' "$sketchdir"/ci.json) printf "\033[93mSkipping $sketchname test for $target, platform: $platform\033[0m\n"
if [ "$len" -eq 0 ]; then printf "\n\n\n"
return 0
fi
if [ $options -eq 0 ] && [ -f $sketchdir/ci.json ]; then
len=`jq -r --arg target $target '.fqbn[$target] | length' $sketchdir/ci.json`
if [ $len -eq 0 ]; then
len=1 len=1
fi fi
else else
len=1 len=1
fi fi
if [ "$len" -eq 1 ]; then if [ $len -eq 1 ]; then
sdkconfig_path="$HOME/.arduino/tests/$target/$sketchname/build.tmp/sdkconfig" # build_dir="$sketchdir/build"
else build_dir="$HOME/.arduino/tests/$sketchname/build.tmp"
sdkconfig_path="$HOME/.arduino/tests/$target/$sketchname/build0.tmp/sdkconfig" report_file="$sketchdir/$target/$sketchname.xml"
fi fi
if [ -f "$sketchdir"/ci.json ]; then for i in `seq 0 $(($len - 1))`
# If the target or platform is listed as false, skip the sketch. Otherwise, include it. do
is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json)
selected_platform=$(jq -r --arg platform "$platform" '.platforms[$platform]' "$sketchdir"/ci.json)
if [[ $is_target == "false" ]] || [[ $selected_platform == "false" ]]; then
printf "\033[93mSkipping %s test for %s, platform: %s\033[0m\n" "$sketchname" "$target" "$platform"
printf "\n\n\n"
return 0
fi
fi
if [ ! -f "$sdkconfig_path" ]; then
printf "\033[93mSketch %s build not found in %s\nMight be due to missing target requirements or build failure\033[0m\n" "$(dirname "$sdkconfig_path")" "$sketchname"
printf "\n\n\n"
return 0
fi
local compiled_target
compiled_target=$(grep -E "CONFIG_IDF_TARGET=" "$sdkconfig_path" | cut -d'"' -f2)
if [ "$compiled_target" != "$target" ]; then
printf "\033[91mError: Sketch %s compiled for %s, expected %s\033[0m\n" "$sketchname" "$compiled_target" "$target"
printf "\n\n\n"
return 1
fi
if [ "$len" -eq 1 ]; then
# build_dir="$sketchdir/build"
build_dir="$HOME/.arduino/tests/$target/$sketchname/build.tmp"
report_file="$sketchdir/$target/$sketchname.xml"
fi
for i in $(seq 0 $((len - 1))); do
fqbn="Default" fqbn="Default"
if [ "$len" -ne 1 ]; then if [ $len -ne 1 ]; then
fqbn=$(jq -r --arg target "$target" --argjson i "$i" '.fqbn[$target] | sort | .[$i]' "$sketchdir"/ci.json) fqbn=`jq -r --arg target $target --argjson i $i '.fqbn[$target] | sort | .[$i]' $sketchdir/ci.json`
elif [ -f "$sketchdir"/ci.json ]; then elif [ -f $sketchdir/ci.json ]; then
has_fqbn=$(jq -r --arg target "$target" '.fqbn[$target]' "$sketchdir"/ci.json) has_fqbn=`jq -r --arg target $target '.fqbn[$target]' $sketchdir/ci.json`
if [ "$has_fqbn" != "null" ]; then if [ "$has_fqbn" != "null" ]; then
fqbn=$(jq -r --arg target "$target" '.fqbn[$target] | .[0]' "$sketchdir"/ci.json) fqbn=`jq -r --arg target $target '.fqbn[$target] | .[0]' $sketchdir/ci.json`
fi fi
fi fi
printf "\033[95mRunning test: %s -- Config: %s\033[0m\n" "$sketchname" "$fqbn" printf "\033[95mRunning test: $sketchname -- Config: $fqbn\033[0m\n"
if [ "$erase_flash" -eq 1 ]; then if [ $erase_flash -eq 1 ]; then
esptool.py -c "$target" erase_flash esptool.py -c $target erase_flash
fi fi
if [ "$len" -ne 1 ]; then if [ $len -ne 1 ]; then
# build_dir="$sketchdir/build$i" # build_dir="$sketchdir/build$i"
build_dir="$HOME/.arduino/tests/$target/$sketchname/build$i.tmp" build_dir="$HOME/.arduino/tests/$sketchname/build$i.tmp"
report_file="$sketchdir/$target/$sketchname$i.xml" report_file="$sketchdir/$target/$sketchname$i.xml"
fi fi
if [ $platform == "wokwi" ]; then if [ $platform == "wokwi" ]; then
extra_args=("--target" "$target" "--embedded-services" "arduino,wokwi" "--wokwi-timeout=$wokwi_timeout") extra_args="--target $target --embedded-services arduino,wokwi --wokwi-timeout=$wokwi_timeout"
if [[ -f "$sketchdir/scenario.yaml" ]]; then if [[ -f "$sketchdir/scenario.yaml" ]]; then
extra_args+=("--wokwi-scenario" "$sketchdir/scenario.yaml") extra_args+=" --wokwi-scenario $sketchdir/scenario.yaml"
fi fi
if [[ -f "$sketchdir/diagram.$target.json" ]]; then if [[ -f "$sketchdir/diagram.$target.json" ]]; then
extra_args+=("--wokwi-diagram" "$sketchdir/diagram.$target.json") extra_args+=" --wokwi-diagram $sketchdir/diagram.$target.json"
fi fi
elif [ $platform == "qemu" ]; then elif [ $platform == "qemu" ]; then
PATH=$HOME/qemu/bin:$PATH PATH=$HOME/qemu/bin:$PATH
extra_args=("--embedded-services" "qemu" "--qemu-image-path" "$build_dir/$sketchname.ino.merged.bin") extra_args="--embedded-services qemu --qemu-image-path $build_dir/$sketchname.ino.merged.bin"
if [ "$target" == "esp32" ] || [ "$target" == "esp32s3" ]; then if [ $target == "esp32" ] || [ $target == "esp32s3" ]; then
extra_args+=("--qemu-prog-path" "qemu-system-xtensa" "--qemu-cli-args=\"-machine $target -m 4M -nographic\"") extra_args+=" --qemu-prog-path qemu-system-xtensa --qemu-cli-args=\"-machine $target -m 4M -nographic\""
elif [ "$target" == "esp32c3" ]; then elif [ $target == "esp32c3" ]; then
extra_args+=("--qemu-prog-path" "qemu-system-riscv32" "--qemu-cli-args=\"-machine $target -icount 3 -nographic\"") extra_args+=" --qemu-prog-path qemu-system-riscv32 --qemu-cli-args=\"-machine $target -icount 3 -nographic\""
else else
printf "\033[91mUnsupported QEMU target: %s\033[0m\n" "$target" printf "\033[91mUnsupported QEMU target: $target\033[0m\n"
exit 1 exit 1
fi fi
else else
extra_args=("--embedded-services" "esp,arduino") extra_args="--embedded-services esp,arduino"
fi fi
rm "$sketchdir"/diagram.json 2>/dev/null || true
result=0 result=0
printf "\033[95mpytest \"%s/test_%s.py\" --build-dir \"%s\" --junit-xml=\"%s\" -o junit_suite_name=%s_%s_%s_%s%s %s\033[0m\n" "$sketchdir" "$sketchname" "$build_dir" "$report_file" "$test_type" "$platform" "$target" "$sketchname" "$i" "${extra_args[*]@Q}" printf "\033[95mpytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args\033[0m\n"
bash -c "set +e; pytest \"$sketchdir/test_$sketchname.py\" --build-dir \"$build_dir\" --junit-xml=\"$report_file\" -o junit_suite_name=${test_type}_${platform}_${target}_${sketchname}${i} ${extra_args[*]@Q}; exit \$?" || result=$? bash -c "set +e; pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args; exit \$?" || result=$?
printf "\n" printf "\n"
if [ $result -ne 0 ]; then if [ $result -ne 0 ]; then
result=0 result=0
printf "\033[95mRetrying test: %s -- Config: %s\033[0m\n" "$sketchname" "$i" printf "\033[95mRetrying test: $sketchname -- Config: $i\033[0m\n"
printf "\033[95mpytest \"%s/test_%s.py\" --build-dir \"%s\" --junit-xml=\"%s\" -o junit_suite_name=%s_%s_%s_%s%s %s\033[0m\n" "$sketchdir" "$sketchname" "$build_dir" "$report_file" "$test_type" "$platform" "$target" "$sketchname" "$i" "${extra_args[*]@Q}" printf "\033[95mpytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args\033[0m\n"
bash -c "set +e; pytest \"$sketchdir/test_$sketchname.py\" --build-dir \"$build_dir\" --junit-xml=\"$report_file\" -o junit_suite_name=${test_type}_${platform}_${target}_${sketchname}${i} ${extra_args[*]@Q}; exit \$?" || result=$? bash -c "set +e; pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args; exit \$?" || result=$?
printf "\n" printf "\n"
if [ $result -ne 0 ]; then if [ $result -ne 0 ]; then
printf "\033[91mFailed test: %s -- Config: %s\033[0m\n\n" "$sketchname" "$i" printf "\033[91mFailed test: $sketchname -- Config: $i\033[0m\n\n"
error=$result error=$result
fi fi
fi fi
done done
@ -142,13 +117,13 @@ chunk_run=0
options=0 options=0
erase=0 erase=0
while [ -n "$1" ]; do while [ ! -z "$1" ]; do
case $1 in case $1 in
-c ) -c )
chunk_run=1 chunk_run=1
;; ;;
-Q ) -Q )
if [ ! -d "$QEMU_PATH" ]; then if [ ! -d $QEMU_PATH ]; then
echo "QEMU path $QEMU_PATH does not exist" echo "QEMU path $QEMU_PATH does not exist"
exit 1 exit 1
fi fi
@ -194,97 +169,97 @@ while [ -n "$1" ]; do
test_type=$1 test_type=$1
;; ;;
* ) * )
break break
;; ;;
esac esac
shift shift
done done
if [ ! $platform == "qemu" ]; then if [ ! $platform == "qemu" ]; then
source "${SCRIPTS_DIR}/install-arduino-ide.sh" source ${SCRIPTS_DIR}/install-arduino-ide.sh
fi fi
# If sketch is provided and test type is not, test type is inferred from the sketch path # If sketch is provided and test type is not, test type is inferred from the sketch path
if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then
if [ -n "$sketch" ]; then if [ -n "$sketch" ]; then
tmp_sketch_path=$(find tests -name "$sketch".ino) tmp_sketch_path=$(find tests -name $sketch.ino)
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")") test_type=$(basename $(dirname $(dirname "$tmp_sketch_path")))
echo "Sketch $sketch test type: $test_type" echo "Sketch $sketch test type: $test_type"
test_folder="$PWD/tests/$test_type" test_folder="$PWD/tests/$test_type"
else else
test_folder="$PWD/tests" test_folder="$PWD/tests"
fi fi
else else
test_folder="$PWD/tests/$test_type" test_folder="$PWD/tests/$test_type"
fi fi
if [ $chunk_run -eq 0 ]; then if [ $chunk_run -eq 0 ]; then
if [ -z "$sketch" ]; then if [ -z $sketch ]; then
echo "ERROR: Sketch name is required for single test run" echo "ERROR: Sketch name is required for single test run"
exit 1 exit 1
fi fi
run_test "$target" "$test_folder"/"$sketch"/"$sketch".ino $options $erase run_test $target $test_folder/$sketch/$sketch.ino $options $erase
exit $? exit $?
else else
if [ "$chunk_max" -le 0 ]; then if [ "$chunk_max" -le 0 ]; then
echo "ERROR: Chunks count must be positive number" echo "ERROR: Chunks count must be positive number"
exit 1 exit 1
fi fi
if [ "$chunk_index" -ge "$chunk_max" ] && [ "$chunk_max" -ge 2 ]; then if [ "$chunk_index" -ge "$chunk_max" ] && [ "$chunk_max" -ge 2 ]; then
echo "ERROR: Chunk index must be less than chunks count" echo "ERROR: Chunk index must be less than chunks count"
exit 1 exit 1
fi fi
set +e set +e
# Ignore requirements as we don't have the libs. The requirements will be checked in the run_test function ${COUNT_SKETCHES} $test_folder $target
${COUNT_SKETCHES} "$test_folder" "$target" "1" sketchcount=$?
sketchcount=$? set -e
set -e sketches=$(cat sketches.txt)
sketches=$(cat sketches.txt) rm -rf sketches.txt
rm -rf sketches.txt
chunk_size=$(( sketchcount / chunk_max )) chunk_size=$(( $sketchcount / $chunk_max ))
all_chunks=$(( chunk_max * chunk_size )) all_chunks=$(( $chunk_max * $chunk_size ))
if [ "$all_chunks" -lt "$sketchcount" ]; then if [ "$all_chunks" -lt "$sketchcount" ]; then
chunk_size=$(( chunk_size + 1 )) chunk_size=$(( $chunk_size + 1 ))
fi fi
start_index=0 start_index=0
end_index=0 end_index=0
if [ "$chunk_index" -ge "$chunk_max" ]; then if [ "$chunk_index" -ge "$chunk_max" ]; then
start_index=$chunk_index start_index=$chunk_index
end_index=$sketchcount end_index=$sketchcount
else else
start_index=$(( chunk_index * chunk_size )) start_index=$(( $chunk_index * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then if [ "$sketchcount" -le "$start_index" ]; then
exit 0 exit 0
fi fi
end_index=$(( $(( chunk_index + 1 )) * chunk_size )) end_index=$(( $(( $chunk_index + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then if [ "$end_index" -gt "$sketchcount" ]; then
end_index=$sketchcount end_index=$sketchcount
fi fi
fi fi
sketchnum=0 start_num=$(( $start_index + 1 ))
error=0 sketchnum=0
error=0
for sketch in $sketches; do for sketch in $sketches; do
sketchnum=$((sketchnum + 1)) sketchnum=$(($sketchnum + 1))
if [ "$sketchnum" -le "$start_index" ] \ if [ "$sketchnum" -le "$start_index" ] \
|| [ "$sketchnum" -gt "$end_index" ]; then || [ "$sketchnum" -gt "$end_index" ]; then
continue continue
fi fi
printf "\033[95mSketch Index %s\033[0m\n" "$((sketchnum - 1))" printf "\033[95mSketch Index $(($sketchnum - 1))\033[0m\n"
exit_code=0 exit_code=0
run_test "$target" "$sketch" $options $erase || exit_code=$? run_test $target $sketch $options $erase || exit_code=$?
if [ $exit_code -ne 0 ]; then if [ $exit_code -ne 0 ]; then
error=$exit_code error=$exit_code
fi fi
done done
exit $error exit $error
fi fi

View file

@ -1,22 +1,20 @@
#!/bin/bash #!/bin/bash
# Disable shellcheck warning about using 'cat' to read a file.
# shellcheck disable=SC2002
# For reference: add tools for all boards by replacing one line in each board # 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" # "[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/" #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/"
if [ ! $# -eq 3 ]; then if [ ! $# -eq 3 ]; then
echo "Bad number of arguments: $#" >&2 echo "Bad number of arguments: $#" >&2
echo "usage: $0 <major> <minor> <patch>" >&2 echo "usage: $0 <major> <minor> <patch>" >&2
exit 1 exit 1
fi fi
re='^[0-9]+$' re='^[0-9]+$'
if [[ ! $1 =~ $re ]] || [[ ! $2 =~ $re ]] || [[ ! $3 =~ $re ]] ; then if [[ ! $1 =~ $re ]] || [[ ! $2 =~ $re ]] || [[ ! $3 =~ $re ]] ; then
echo "error: Not a valid version: $1.$2.$3" >&2 echo "error: Not a valid version: $1.$2.$3" >&2
echo "usage: $0 <major> <minor> <patch>" >&2 echo "usage: $0 <major> <minor> <patch>" >&2
exit 1 exit 1
fi fi
ESP_ARDUINO_VERSION_MAJOR="$1" ESP_ARDUINO_VERSION_MAJOR="$1"
@ -24,15 +22,7 @@ ESP_ARDUINO_VERSION_MINOR="$2"
ESP_ARDUINO_VERSION_PATCH="$3" ESP_ARDUINO_VERSION_PATCH="$3"
ESP_ARDUINO_VERSION="$ESP_ARDUINO_VERSION_MAJOR.$ESP_ARDUINO_VERSION_MINOR.$ESP_ARDUINO_VERSION_PATCH" 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/')
if [ -z "$ESP_IDF_VERSION" ]; then
echo "Error: ESP-IDF version not found in push.yml" >&2
exit 1
fi
echo "New Arduino Version: $ESP_ARDUINO_VERSION" echo "New Arduino Version: $ESP_ARDUINO_VERSION"
echo "ESP-IDF Version: $ESP_IDF_VERSION"
echo "Updating platform.txt..." echo "Updating platform.txt..."
cat platform.txt | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > __platform.txt && mv __platform.txt platform.txt cat platform.txt | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > __platform.txt && mv __platform.txt platform.txt
@ -40,28 +30,17 @@ cat platform.txt | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > __platfor
echo "Updating package.json..." echo "Updating package.json..."
cat package.json | sed "s/.*\"version\":.*/ \"version\": \"$ESP_ARDUINO_VERSION\",/g" > __package.json && mv __package.json package.json cat package.json | sed "s/.*\"version\":.*/ \"version\": \"$ESP_ARDUINO_VERSION\",/g" > __package.json && mv __package.json package.json
echo "Updating docs/conf_common.py..."
cat docs/conf_common.py | \
sed "s/.. |version| replace:: .*/.. |version| replace:: $ESP_ARDUINO_VERSION/g" | \
sed "s/.. |idf_version| replace:: .*/.. |idf_version| replace:: $ESP_IDF_VERSION/g" > docs/__conf_common.py && mv docs/__conf_common.py docs/conf_common.py
echo "Updating .gitlab/workflows/common.yml..."
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 cores/esp32/esp_arduino_version.h..." echo "Updating cores/esp32/esp_arduino_version.h..."
cat cores/esp32/esp_arduino_version.h | \ cat cores/esp32/esp_arduino_version.h | \
sed "s/#define ESP_ARDUINO_VERSION_MAJOR.*/#define ESP_ARDUINO_VERSION_MAJOR $ESP_ARDUINO_VERSION_MAJOR/g" | \ sed "s/#define ESP_ARDUINO_VERSION_MAJOR.*/#define ESP_ARDUINO_VERSION_MAJOR $ESP_ARDUINO_VERSION_MAJOR/g" | \
sed "s/#define ESP_ARDUINO_VERSION_MINOR.*/#define ESP_ARDUINO_VERSION_MINOR $ESP_ARDUINO_VERSION_MINOR/g" | \ sed "s/#define ESP_ARDUINO_VERSION_MINOR.*/#define ESP_ARDUINO_VERSION_MINOR $ESP_ARDUINO_VERSION_MINOR/g" | \
sed "s/#define ESP_ARDUINO_VERSION_PATCH.*/#define ESP_ARDUINO_VERSION_PATCH $ESP_ARDUINO_VERSION_PATCH/g" > __esp_arduino_version.h && mv __esp_arduino_version.h cores/esp32/esp_arduino_version.h sed "s/#define ESP_ARDUINO_VERSION_PATCH.*/#define ESP_ARDUINO_VERSION_PATCH $ESP_ARDUINO_VERSION_PATCH/g" > __esp_arduino_version.h && mv __esp_arduino_version.h cores/esp32/esp_arduino_version.h
libraries=$(find libraries -maxdepth 1 -mindepth 1 -type d -exec basename {} \;) for lib in `ls libraries`; do
for lib in $libraries; do if [ -f "libraries/$lib/library.properties" ]; then
if [ -f "libraries/$lib/library.properties" ]; then echo "Updating Library $lib..."
echo "Updating Library $lib..." cat "libraries/$lib/library.properties" | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > "libraries/$lib/__library.properties" && mv "libraries/$lib/__library.properties" "libraries/$lib/library.properties"
cat "libraries/$lib/library.properties" | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > "libraries/$lib/__library.properties" && mv "libraries/$lib/__library.properties" "libraries/$lib/library.properties" fi
fi
done done
exit 0 exit 0

View file

@ -1,236 +0,0 @@
#!/usr/bin/env python3
# This script is used to re-package the esptool if needed and update the JSON file
# for the Arduino ESP32 platform.
#
# The script has only been tested on macOS.
#
# For regular esptool releases, the generated packages already contain the correct permissions,
# extensions and are uploaded to the GitHub release assets. In this case, the script will only
# update the JSON file with the information from the GitHub release.
#
# The script can be used in two modes:
# 1. Local build: The build artifacts must be already downloaded and extracted in the base_folder.
# This is useful for esptool versions that are not yet released and that are grabbed from the
# GitHub build artifacts.
# 2. Release build: The script will get the release information from GitHub and update the JSON file.
# This is useful for esptool versions that are already released and that are uploaded to the
# GitHub release assets.
#
# For local build, the artifacts must be already downloaded and extracted in the base_folder
# set with the -l option.
# For example, a base folder "esptool" should contain the following folders extracted directly
# from the GitHub build artifacts:
# esptool/esptool-linux-aarch64
# esptool/esptool-linux-amd64
# esptool/esptool-linux-armv7
# esptool/esptool-macos-amd64
# esptool/esptool-macos-arm64
# esptool/esptool-windows-amd64
import argparse
import json
import os
import shutil
import stat
import tarfile
import zipfile
import hashlib
import requests
from pathlib import Path
def compute_sha256(filepath):
sha256 = hashlib.sha256()
with open(filepath, "rb") as f:
for block in iter(lambda: f.read(4096), b""):
sha256.update(block)
return f"SHA-256:{sha256.hexdigest()}"
def get_file_size(filepath):
return os.path.getsize(filepath)
def update_json_for_host(tmp_json_path, version, host, url, archiveFileName, checksum, size):
with open(tmp_json_path) as f:
data = json.load(f)
for pkg in data.get("packages", []):
for tool in pkg.get("tools", []):
if tool.get("name") == "esptool_py":
tool["version"] = version
if url is None:
# If the URL is not set, we need to find the old URL and update it
for system in tool.get("systems", []):
if system.get("host") == host:
url = system.get("url").replace(system.get("archiveFileName"), archiveFileName)
break
else:
print(f"No old URL found for host {host}. Using empty URL.")
url = ""
# Preserve existing systems order and update or append the new system
systems = tool.get("systems", [])
system_updated = False
for i, system in enumerate(systems):
if system.get("host") == host:
systems[i] = {
"host": host,
"url": url,
"archiveFileName": archiveFileName,
"checksum": checksum,
"size": str(size),
}
system_updated = True
break
if not system_updated:
systems.append({
"host": host,
"url": url,
"archiveFileName": archiveFileName,
"checksum": checksum,
"size": str(size),
})
tool["systems"] = systems
with open(tmp_json_path, "w") as f:
json.dump(data, f, indent=2, sort_keys=False, ensure_ascii=False)
f.write("\n")
def update_tools_dependencies(tmp_json_path, version):
with open(tmp_json_path) as f:
data = json.load(f)
for pkg in data.get("packages", []):
for platform in pkg.get("platforms", []):
for dep in platform.get("toolsDependencies", []):
if dep.get("name") == "esptool_py":
dep["version"] = version
with open(tmp_json_path, "w") as f:
json.dump(data, f, indent=2, sort_keys=False, ensure_ascii=False)
f.write("\n")
def create_archives(version, base_folder):
archive_files = []
for dirpath in Path(base_folder).glob("esptool-*"):
if not dirpath.is_dir():
continue
base = dirpath.name[len("esptool-"):]
if "windows" in dirpath.name:
zipfile_name = f"esptool-v{version}-{base}.zip"
print(f"Creating {zipfile_name} from {dirpath} ...")
with zipfile.ZipFile(zipfile_name, "w", zipfile.ZIP_DEFLATED) as zipf:
for root, _, files in os.walk(dirpath):
for file in files:
full_path = os.path.join(root, file)
zipf.write(full_path, os.path.relpath(full_path, start=dirpath))
archive_files.append(zipfile_name)
else:
tarfile_name = f"esptool-v{version}-{base}.tar.gz"
print(f"Creating {tarfile_name} from {dirpath} ...")
for root, dirs, files in os.walk(dirpath):
for name in dirs + files:
os.chmod(os.path.join(root, name), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
stat.S_IRGRP | stat.S_IXGRP |
stat.S_IROTH | stat.S_IXOTH)
with tarfile.open(tarfile_name, "w:gz") as tar:
tar.add(dirpath, arcname=dirpath.name)
archive_files.append(tarfile_name)
return archive_files
def determine_hosts(archive_name):
if "linux-amd64" in archive_name:
return ["x86_64-pc-linux-gnu"]
elif "linux-armv7" in archive_name:
return ["arm-linux-gnueabihf"]
elif "linux-aarch64" in archive_name:
return ["aarch64-linux-gnu"]
elif "macos-amd64" in archive_name:
return ["x86_64-apple-darwin"]
elif "macos-arm64" in archive_name:
return ["arm64-apple-darwin"]
elif "windows-amd64" in archive_name:
return ["x86_64-mingw32", "i686-mingw32"]
else:
return []
def update_json_from_local_build(tmp_json_path, version, base_folder, archive_files):
for archive in archive_files:
print(f"Processing archive: {archive}")
hosts = determine_hosts(archive)
if not hosts:
print(f"Skipping unknown archive type: {archive}")
continue
archive_path = Path(archive)
checksum = compute_sha256(archive_path)
size = get_file_size(archive_path)
for host in hosts:
update_json_for_host(tmp_json_path, version, host, None, archive_path.name, checksum, size)
def update_json_from_release(tmp_json_path, version, release_info):
assets = release_info.get("assets", [])
for asset in assets:
if (asset.get("name").endswith(".tar.gz") or asset.get("name").endswith(".zip")) and "esptool" in asset.get("name"):
asset_fname = asset.get("name")
print(f"Processing asset: {asset_fname}")
hosts = determine_hosts(asset_fname)
if not hosts:
print(f"Skipping unknown archive type: {asset_fname}")
continue
asset_url = asset.get("browser_download_url")
asset_checksum = asset.get("digest").replace("sha256:", "SHA-256:")
asset_size = asset.get("size")
if asset_checksum is None:
asset_checksum = ""
print(f"Asset {asset_fname} has no checksum. Please set the checksum in the JSON file.")
for host in hosts:
update_json_for_host(tmp_json_path, version, host, asset_url, asset_fname, asset_checksum, asset_size)
def get_release_info(version):
url = f"https://api.github.com/repos/espressif/esptool/releases/tags/v{version}"
response = requests.get(url)
response.raise_for_status()
return response.json()
def main():
parser = argparse.ArgumentParser(description="Repack esptool and update JSON metadata.")
parser.add_argument("version", help="Version of the esptool (e.g. 5.0.dev1)")
parser.add_argument("-l", "--local", dest="base_folder", help="Enable local build mode and set the base folder with unpacked artifacts")
args = parser.parse_args()
script_dir = Path(__file__).resolve().parent
json_path = (script_dir / "../../package/package_esp32_index.template.json").resolve()
tmp_json_path = Path(str(json_path) + ".tmp")
shutil.copy(json_path, tmp_json_path)
local_build = args.base_folder is not None
if local_build:
os.chdir(args.base_folder)
os.environ['COPYFILE_DISABLE'] = 'true' # this disables including resource forks in tar files on macOS
# Clear any existing archive files
for file in Path(args.base_folder).glob("esptool-*.*"):
file.unlink()
archive_files = create_archives(args.version, args.base_folder)
update_json_from_local_build(tmp_json_path, args.version, args.base_folder, archive_files)
else:
release_info = get_release_info(args.version)
update_json_from_release(tmp_json_path, args.version, release_info)
print(f"Updating esptool version fields to {args.version}")
update_tools_dependencies(tmp_json_path, args.version)
shutil.move(tmp_json_path, json_path)
print(f"Done. JSON updated at {json_path}")
if __name__ == "__main__":
main()

View file

@ -1,12 +1,11 @@
#!/bin/bash #!/bin/bash
CHANGED_FILES=$1 CHANGED_FILES=$1
echo "Pushing '$CHANGED_FILES' as github-actions[bot]" echo "Pushing '$CHANGED_FILES' as github-actions[bot]"
git config --global github.user "github-actions[bot]" git config --global github.user "github-actions[bot]"
git config --global user.name "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 config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
for tool in $CHANGED_FILES; do for tool in $CHANGED_FILES; do
git add tools/"$tool".exe git add tools/$tool.exe
done done
git commit -m "change(tools): Push generated binaries to PR" git commit -m "change(tools): Push generated binaries to PR"
git push git push

View file

@ -1,6 +1,6 @@
name: Boards Test - Remote trigger name: Boards Test - Remote trigger
# The workflow will run on remote dispatch with event-type set to "test-boards" # The workflow will run on remote dispath with event-type set to "test-boards"
on: on:
repository_dispatch: repository_dispatch:
types: [test-boards] types: [test-boards]
@ -15,12 +15,13 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
ref: ${{ github.event.client_payload.branch }} ref: ${{ github.event.client_payload.branch }}
- name: Get boards fqbns - name: Get boards fqbns
run: bash .github/scripts/find_all_boards.sh run:
bash .github/scripts/find_all_boards.sh
setup-chunks: setup-chunks:
needs: find-boards needs: find-boards
@ -32,17 +33,18 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
ref: ${{ github.event.client_payload.branch }} ref: ${{ github.event.client_payload.branch }}
- run: npm install - run: npm install
- name: Setup jq - name: Setup jq
uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1 uses: dcarbone/install-jq-action@v1.0.1
- id: set-test-chunks - id: set-test-chunks
name: Set Chunks name: Set Chunks
run: echo "test-chunks<<EOF" >> $GITHUB_OUTPUT run:
echo "test-chunks<<EOF" >> $GITHUB_OUTPUT
echo "$( jq -nc '${{ needs.find-boards.outputs.fqbns }} | [_nwise( ${{ needs.find-boards.outputs.board-count }}/15 | ceil)]')" >> $GITHUB_OUTPUT echo "$( jq -nc '${{ needs.find-boards.outputs.fqbns }} | [_nwise( ${{ needs.find-boards.outputs.board-count }}/15 | ceil)]')" >> $GITHUB_OUTPUT
@ -64,17 +66,18 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
ref: ${{ github.event.client_payload.branch }} ref: ${{ github.event.client_payload.branch }}
- name: Echo FQBNS to file - name: Echo FQBNS to file
run: echo "$FQBN" > fqbns.json run:
echo "$FQBN" > fqbns.json
env: env:
FQBN: ${{ toJSON(matrix.chunk) }} FQBN: ${{ toJSON(matrix.chunk) }}
- name: Compile sketch - name: Compile sketch
uses: P-R-O-C-H-Y/compile-sketches@a62f069b92dc8f5053da4ac439ea6d1950cf6379 # main uses: P-R-O-C-H-Y/compile-sketches@main
with: with:
platforms: | platforms: |
${{ env.REPOSITORY }} ${{ env.REPOSITORY }}
@ -85,4 +88,5 @@ jobs:
enable-warnings-report: false enable-warnings-report: false
cli-compile-flags: | cli-compile-flags: |
- --warnings="all" - --warnings="all"
sketch-paths: "- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino" sketch-paths:
"- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino"

View file

@ -4,9 +4,9 @@ name: Boards Test
on: on:
pull_request: pull_request:
paths: paths:
- "boards.txt" - 'boards.txt'
- "libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino" - 'libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino'
- ".github/workflows/boards.yml" - '.github/workflows/boards.yml'
env: env:
# It's convenient to set variables for values used multiple times in the workflow # It's convenient to set variables for values used multiple times in the workflow
@ -22,13 +22,14 @@ jobs:
steps: steps:
# This step makes the contents of the repository available to the workflow # This step makes the contents of the repository available to the workflow
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
- name: Setup jq - name: Setup jq
uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1 uses: dcarbone/install-jq-action@v1.0.1
- name: Get board name - name: Get board name
run: bash .github/scripts/find_new_boards.sh ${{ github.repository }} ${{github.base_ref}} run:
bash .github/scripts/find_new_boards.sh ${{ github.repository }} ${{github.event.number}}
test-boards: test-boards:
needs: find-boards needs: find-boards
@ -41,13 +42,12 @@ jobs:
name: "espressif:esp32" name: "espressif:esp32"
strategy: strategy:
fail-fast: false
matrix: ${{ fromJson(needs.find-boards.outputs.fqbns) }} matrix: ${{ fromJson(needs.find-boards.outputs.fqbns) }}
steps: steps:
# This step makes the contents of the repository available to the workflow # This step makes the contents of the repository available to the workflow
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
- name: Check if build.board is uppercase - name: Check if build.board is uppercase
run: | run: |
@ -60,7 +60,7 @@ jobs:
fi fi
- name: Get libs cache - name: Get libs cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache@v4
with: with:
key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }} key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }}
path: | path: |
@ -73,7 +73,7 @@ jobs:
./tools/xtensa-* ./tools/xtensa-*
- name: Compile sketch - name: Compile sketch
uses: P-R-O-C-H-Y/compile-sketches@a62f069b92dc8f5053da4ac439ea6d1950cf6379 # main uses: P-R-O-C-H-Y/compile-sketches@main
with: with:
platforms: | platforms: |
${{ env.REPOSITORY }} ${{ env.REPOSITORY }}
@ -84,5 +84,6 @@ jobs:
cli-compile-flags: | cli-compile-flags: |
- --warnings="all" - --warnings="all"
exit-on-fail: true exit-on-fail: true
sketch-paths: "- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino" sketch-paths:
"- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino"
verbose: true verbose: true

View file

@ -3,22 +3,22 @@ name: Build Python Tools
on: on:
pull_request: pull_request:
paths: paths:
- ".github/workflows/build_py_tools.yml" - '.github/workflows/build_py_tools.yml'
- "tools/get.py" - 'tools/get.py'
- "tools/espota.py" - 'tools/espota.py'
- "tools/gen_esp32part.py" - 'tools/gen_esp32part.py'
- "tools/gen_insights_package.py" - 'tools/gen_insights_package.py'
jobs: jobs:
find-changed-tools: find-changed-tools:
name: Check if tools have been changed name: Check if tools have been changed
runs-on: ubuntu-latest runs-on: ubuntu-20.04
outputs: outputs:
any_changed: ${{ steps.verify-changed-files.outputs.any_changed }} any_changed: ${{ steps.verify-changed-files.outputs.any_changed }}
all_changed_files: ${{ steps.verify-changed-files.outputs.all_changed_files }} all_changed_files: ${{ steps.verify-changed-files.outputs.all_changed_files }}
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
fetch-depth: 2 fetch-depth: 2
ref: ${{ github.event.pull_request.head.ref }} ref: ${{ github.event.pull_request.head.ref }}
@ -30,17 +30,16 @@ jobs:
echo "Make sure you are using a branch inside the repository and not a fork." echo "Make sure you are using a branch inside the repository and not a fork."
- name: Verify Python Tools Changed - name: Verify Python Tools Changed
uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1 uses: tj-actions/changed-files@v41
id: verify-changed-files id: verify-changed-files
with: with:
fetch_depth: "2" fetch_depth: '2'
since_last_remote_commit: "true" since_last_remote_commit: 'true'
files: | files: |
tools/get.py tools/get.py
tools/espota.py tools/espota.py
tools/gen_esp32part.py tools/gen_esp32part.py
tools/gen_insights_package.py tools/gen_insights_package.py
- name: List all changed files - name: List all changed files
shell: bash shell: bash
run: | run: |
@ -56,21 +55,23 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [windows-latest, macos-latest, ubuntu-latest, ubuntu-24.04-arm] os: [windows-latest, macos-latest, ubuntu-20.04, ARM]
include: include:
- os: windows-latest - os: windows-latest
TARGET: win64 TARGET: win64
EXTEN: .exe EXTEN: .exe
SEPARATOR: ";" SEPARATOR: ';'
- os: macos-latest - os: macos-latest
TARGET: macos TARGET: macos
SEPARATOR: ":" SEPARATOR: ':'
- os: ubuntu-latest - os: ubuntu-20.04
TARGET: linux-amd64 TARGET: linux-amd64
SEPARATOR: ":" SEPARATOR: ':'
- os: ubuntu-24.04-arm - os: ARM
TARGET: arm CONTAINER: python:3.8-bullseye
SEPARATOR: ":" TARGET: arm
SEPARATOR: ':'
container: ${{ matrix.CONTAINER }} # use python container on ARM
env: env:
DISTPATH: pytools-${{ matrix.TARGET }} DISTPATH: pytools-${{ matrix.TARGET }}
PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi" PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi"
@ -89,30 +90,27 @@ jobs:
for tool in ${{ env.CHANGED_TOOLS }}; do for tool in ${{ env.CHANGED_TOOLS }}; do
echo "tool $tool was changed" echo "tool $tool was changed"
done done
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
token: ${{ secrets.TOOLS_UPLOAD_PAT }} token: ${{ secrets.TOOLS_UPLOAD_PAT }}
ref: ${{ github.event.pull_request.head.ref }} ref: ${{ github.event.pull_request.head.ref }}
- name: Set up Python 3.8 - name: Set up Python 3.8
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 # Skip setting python on ARM because of missing compatibility: https://github.com/actions/setup-python/issues/108
if: matrix.os != 'ARM'
uses: actions/setup-python@master
with: with:
python-version: 3.8 python-version: 3.8
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install pyinstaller requests pip install pyinstaller requests
- name: Build with PyInstaller - name: Build with PyInstaller
shell: bash shell: bash
run: | run: |
for tool in ${{ env.CHANGED_TOOLS }}; do for tool in ${{ env.CHANGED_TOOLS }}; do
pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=.github/pytools/espressif.ico tools/$tool.py pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=.github/pytools/espressif.ico tools/$tool.py
done done
- name: Sign binaries - name: Sign binaries
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
env: env:
@ -125,14 +123,12 @@ jobs:
{ {
./.github/pytools/Sign-File.ps1 -Path ./${{ env.DISTPATH }}/$node.exe ./.github/pytools/Sign-File.ps1 -Path ./${{ env.DISTPATH }}/$node.exe
} }
- name: Test binaries - name: Test binaries
shell: bash shell: bash
run: | run: |
for tool in ${{ env.CHANGED_TOOLS }}; do for tool in ${{ env.CHANGED_TOOLS }}; do
./${{ env.DISTPATH }}/$tool${{ matrix.EXTEN }} -h ./${{ env.DISTPATH }}/$tool${{ matrix.EXTEN }} -h
done done
- name: Push binary to tools - name: Push binary to tools
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
env: env:
@ -143,9 +139,8 @@ jobs:
cp -f ./${{ env.DISTPATH }}/$tool.exe tools/$tool.exe cp -f ./${{ env.DISTPATH }}/$tool.exe tools/$tool.exe
done done
bash .github/scripts/upload_py_tools.sh "${{ env.CHANGED_TOOLS }}" bash .github/scripts/upload_py_tools.sh "${{ env.CHANGED_TOOLS }}"
- name: Archive artifact - name: Archive artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@master
with: with:
name: ${{ env.DISTPATH }} name: ${{ env.DISTPATH }}
path: ${{ env.DISTPATH }} path: ${{ env.DISTPATH }}

View file

@ -1,31 +0,0 @@
name: CodeQL Actions Analysis
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
paths:
- ".github/workflows/*.yml"
- ".github/workflows/*.yaml"
jobs:
codeql-analysis:
name: CodeQL Actions Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Initialize CodeQL
uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
with:
languages: actions
config-file: ./.github/codeql/codeql-config.yml
- name: Run CodeQL Analysis
uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
with:
category: "Analysis: Actions"

View file

@ -1,30 +0,0 @@
name: CodeQL Python Analysis
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
paths:
- "**/*.py"
jobs:
codeql-analysis:
name: CodeQL Python Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Initialize CodeQL
uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
with:
languages: python
config-file: ./.github/codeql/codeql-config.yml
- name: Run CodeQL Analysis
uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
with:
category: "Analysis: Python"

View file

@ -11,18 +11,12 @@ jobs:
pull-request-style-linter: pull-request-style-linter:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out PR head - name: Check out PR head
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: DangerJS pull request linter - name: DangerJS pull request linter
uses: espressif/shared-github-dangerjs@fb17367fd3e8ff7412603b8e946d9b19ffdb2d7f # v1 uses: espressif/shared-github-dangerjs@v1
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
instructions-cla-link: "https://cla-assistant.io/espressif/arduino-esp32"
instructions-contributions-file: "docs/en/contributing.rst"
rule-max-commits: "false"
rule-target-branch: "false"
commit-messages-min-summary-length: "10"

View file

@ -3,17 +3,18 @@ name: Documentation Build and Deploy CI
on: on:
push: push:
branches: branches:
- master - master
- release/v2.x - release/v2.x
paths: paths:
- "docs/**" - 'docs/**'
- ".github/workflows/docs_build.yml" - '.github/workflows/docs_build.yml'
pull_request: pull_request:
paths: paths:
- "docs/**" - 'docs/**'
- ".github/workflows/docs_build.yml" - '.github/workflows/docs_build.yml'
jobs: jobs:
build-docs: build-docs:
name: Build ESP-Docs name: Build ESP-Docs
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
@ -21,28 +22,25 @@ jobs:
run: run:
shell: bash shell: bash
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
with: with:
submodules: true submodules: true
- uses: actions/setup-python@v5
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 with:
with: cache-dependency-path: docs/requirements.txt
cache-dependency-path: docs/requirements.txt cache: 'pip'
cache: "pip" python-version: '3.10'
python-version: "3.10" - name: Build
run: |
- name: Build sudo apt update
run: | sudo apt install python3-pip python3-setuptools
sudo apt update # GitHub CI installs pip3 and setuptools outside the path.
sudo apt install python3-pip python3-setuptools # Update the path to include them and run.
# GitHub CI installs pip3 and setuptools outside the path. cd ./docs
# Update the path to include them and run. PATH=/home/runner/.local/bin:$PATH pip3 install -r requirements.txt --prefer-binary
cd ./docs PATH=/home/runner/.local/bin:$PATH SPHINXOPTS="-W" build-docs -l en
PATH=/home/runner/.local/bin:$PATH pip3 install -r requirements.txt --prefer-binary - name: Archive Docs
PATH=/home/runner/.local/bin:$PATH SPHINXOPTS="-W" build-docs -l en uses: actions/upload-artifact@v4
with:
- name: Archive Docs name: docs
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 path: docs
with:
name: docs
path: docs

View file

@ -7,11 +7,11 @@ on:
- completed - completed
push: push:
branches: branches:
- release/v2.x - release/v2.x
- master - master
paths: paths:
- "docs/**" - 'docs/**'
- ".github/workflows/docs_deploy.yml" - '.github/workflows/docs_deploy.yml'
jobs: jobs:
deploy-prod-docs: deploy-prod-docs:
@ -21,42 +21,39 @@ jobs:
run: run:
shell: bash shell: bash
steps: steps:
- name: Check if release workflow is successful - name: Check if release workflow is successful
if: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.conclusion != 'success' }} if: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.conclusion != 'success' }}
run: | run: |
echo "Release workflow failed. Exiting..." echo "Release workflow failed. Exiting..."
exit 1 exit 1
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with:
with: submodules: true
submodules: true - uses: actions/setup-python@v5
with:
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 cache-dependency-path: docs/requirements.txt
with: cache: 'pip'
cache-dependency-path: docs/requirements.txt python-version: '3.10'
cache: "pip" - name: Deploy Documentation
python-version: "3.10" env:
# Deploy to production server
- name: Deploy Documentation # DOCS_BUILD_DIR: "./docs/_build/"
env: DOCS_DEPLOY_PRIVATEKEY: ${{ secrets.DOCS_KEY }}
# Deploy to production server DOCS_DEPLOY_PATH: ${{ secrets.DOCS_PATH }}
# DOCS_BUILD_DIR: "./docs/_build/" DOCS_DEPLOY_SERVER: ${{ secrets.DOCS_SERVER }}
DOCS_DEPLOY_PRIVATEKEY: ${{ secrets.DOCS_KEY }} DOCS_DEPLOY_SERVER_USER: ${{ secrets.DOCS_USER }}
DOCS_DEPLOY_PATH: ${{ secrets.DOCS_PATH }} DOCS_DEPLOY_URL_BASE: ${{ secrets.DOCS_URL }}
DOCS_DEPLOY_SERVER: ${{ secrets.DOCS_SERVER }} run: |
DOCS_DEPLOY_SERVER_USER: ${{ secrets.DOCS_USER }} sudo apt update
DOCS_DEPLOY_URL_BASE: ${{ secrets.DOCS_URL }} sudo apt install python3-pip python3-setuptools
run: | source ./docs/utils.sh
sudo apt update add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER
sudo apt install python3-pip python3-setuptools export GIT_VER=$(git describe --always)
source ./docs/utils.sh echo "PIP install requirements..."
add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER pip3 install --user -r ./docs/requirements.txt
export GIT_VER=$(git describe --always) echo "Building the Docs..."
echo "PIP install requirements..." cd ./docs && build-docs -l en
pip3 install --user -r ./docs/requirements.txt echo "Deploy the Docs..."
echo "Building the Docs..." export DOCS_BUILD_DIR=$GITHUB_WORKSPACE/docs/
cd ./docs && build-docs -l en cd $GITHUB_WORKSPACE/docs
echo "Deploy the Docs..." deploy-docs
export DOCS_BUILD_DIR=$GITHUB_WORKSPACE/docs/
cd $GITHUB_WORKSPACE/docs
deploy-docs

View file

@ -3,22 +3,21 @@ name: GitHub Pages CI
on: on:
push: push:
branches: branches:
- master - master
- pages - pages
paths: paths:
- "README.md" - 'README.md'
- ".github/scripts/on-pages.sh" - '.github/scripts/on-pages.sh'
- ".github/workflows/gh-pages.yml" - '.github/workflows/gh-pages.yml'
jobs: jobs:
build-pages: build-pages:
name: Build GitHub Pages name: Build GitHub Pages
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Copy Files
env:
- name: Copy Files GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
env: run: bash ./.github/scripts/on-pages.sh
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash ./.github/scripts/on-pages.sh

View file

@ -9,8 +9,7 @@
{ {
"name": "ArduinoBLE", "name": "ArduinoBLE",
"exclude_targets": [ "exclude_targets": [
"esp32s2", "esp32s2"
"esp32p4"
], ],
"sketch_path": [ "sketch_path": [
"~/Arduino/libraries/ArduinoBLE/examples/Central/Scan/Scan.ino" "~/Arduino/libraries/ArduinoBLE/examples/Central/Scan/Scan.ino"
@ -24,44 +23,16 @@
] ]
}, },
{ {
"source-url": "https://github.com/ESP32Async/ESPAsyncWebServer.git", "source-url": "https://github.com/me-no-dev/ESPAsyncWebServer.git",
"required-libs": [ "required-libs": [
{"source-url": "https://github.com/ESP32Async/AsyncTCP.git"} {"source-url": "https://github.com/me-no-dev/AsyncTCP.git"}
], ],
"exclude_targets": [], "exclude_targets": [],
"sketch_path": [ "sketch_path": [
"~/Arduino/libraries/ESPAsyncWebServer/examples/Auth/Auth.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/CORS/CORS.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino", "~/Arduino/libraries/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/CatchAllHandler/CatchAllHandler.ino", "~/Arduino/libraries/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/ChunkResponse/ChunkResponse.ino", "~/Arduino/libraries/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/ChunkRetryResponse/ChunkRetryResponse.ino", "~/Arduino/libraries/ESPAsyncWebServer/examples/simple_server/simple_server.ino"
"~/Arduino/libraries/ESPAsyncWebServer/examples/EndBegin/EndBegin.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/Filters/Filters.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/FlashResponse/FlashResponse.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/HeaderManipulation/HeaderManipulation.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/Headers/Headers.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/Json/Json.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/Logging/Logging.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/MessagePack/MessagePack.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/Middleware/Middleware.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/Params/Params.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/PartitionDownloader/PartitionDownloader.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/PerfTests/PerfTests.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/RateLimit/RateLimit.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/Redirect/Redirect.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/RequestContinuation/RequestContinuation.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/RequestContinuationComplete/RequestContinuationComplete.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/ResumableDownload/ResumableDownload.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/Rewrite/Rewrite.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/ServerSentEvents/ServerSentEvents.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/ServerState/ServerState.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/SkipServerMiddleware/SkipServerMiddleware.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/SlowChunkResponse/SlowChunkResponse.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/StaticFile/StaticFile.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/Templates/Templates.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/Upload/Upload.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/WebSocket/WebSocket.ino"
] ]
}, },
{ {

View file

@ -7,7 +7,7 @@ on:
# Schedule weekly builds on every Sunday at 4 am # Schedule weekly builds on every Sunday at 4 am
schedule: schedule:
- cron: "0 4 * * SUN" - cron: '0 4 * * SUN'
concurrency: concurrency:
group: libs-${{ github.event.pull_request.number || github.ref }} group: libs-${{ github.event.pull_request.number || github.ref }}
@ -27,6 +27,7 @@ jobs:
contains(github.event.pull_request.labels.*.name, 'lib_test') || contains(github.event.pull_request.labels.*.name, 'lib_test') ||
(github.event_name == 'schedule' && github.repository == 'espressif/arduino-esp32') (github.event_name == 'schedule' && github.repository == 'espressif/arduino-esp32')
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
REPOSITORY: | REPOSITORY: |
- source-path: '.' - source-path: '.'
@ -41,7 +42,6 @@ jobs:
- esp32s3 - esp32s3
- esp32c6 - esp32c6
- esp32h2 - esp32h2
- esp32p4
include: include:
- target: esp32 - target: esp32
@ -56,16 +56,15 @@ jobs:
fqbn: espressif:esp32:esp32c6 fqbn: espressif:esp32:esp32c6
- target: esp32h2 - target: esp32h2
fqbn: espressif:esp32:esp32h2 fqbn: espressif:esp32:esp32h2
- target: esp32p4
fqbn: espressif:esp32:esp32p4
steps: steps:
# This step makes the contents of the repository available to the workflow # This step makes the contents of the repository available to the workflow
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
- name: Compile sketch - name: Compile sketch
uses: P-R-O-C-H-Y/compile-sketches@a62f069b92dc8f5053da4ac439ea6d1950cf6379 # main uses: P-R-O-C-H-Y/compile-sketches@main
with: with:
platforms: | platforms: |
${{ env.REPOSITORY }} ${{ env.REPOSITORY }}
@ -80,42 +79,44 @@ jobs:
- --warnings="all" - --warnings="all"
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@v4
with: with:
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}-${{ matrix.target }} name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}-${{ matrix.target }}
path: ${{ env.SKETCHES_REPORTS_PATH }} path: ${{ env.SKETCHES_REPORTS_PATH }}
report-to-file: report-to-file:
needs: compile-sketch # Wait for the compile job to finish to get the data for the report needs: compile-sketch # Wait for the compile job to finish to get the data for the report
if: github.event_name == 'schedule' # Only run the job when the workflow is triggered by a schedule if: github.event_name == 'schedule' # Only run the job when the workflow is triggered by a schedule
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
# Check out repository # Check out repository
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
token: ${{ env.GITHUB_TOKEN }} token: ${{ env.GITHUB_TOKEN }}
fetch-depth: "0" fetch-depth: '0'
- name: Switch branch - name: Switch branch
run: git checkout remotes/origin/gh-pages run:
git checkout remotes/origin/gh-pages
# This step is needed to get the size data produced by the compile jobs # This step is needed to get the size data produced by the compile jobs
- name: Download sketches reports artifact - name: Download sketches reports artifact
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 uses: actions/download-artifact@v4
with: with:
pattern: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}-* pattern: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}-*
merge-multiple: true merge-multiple: true
path: ${{ env.SKETCHES_REPORTS_PATH }} path: ${{ env.SKETCHES_REPORTS_PATH }}
- name: Report results - name: Report results
uses: P-R-O-C-H-Y/report-size-deltas@4a79caa6dcc3579024293638b97156106edc588e # main uses: P-R-O-C-H-Y/report-size-deltas@main
with: with:
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
destination-file: ${{ env.RESULT_LIBRARY_TEST_FILE }} destination-file: ${{ env.RESULT_LIBRARY_TEST_FILE }}
- name: Append file with action URL - name: Append file with action URL
run: echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_LIBRARY_TEST_FILE }} run:
echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_LIBRARY_TEST_FILE }}
- name: Push to github repo - name: Push to github repo
run: | run: |
@ -136,9 +137,8 @@ jobs:
env: env:
PR_NUM: ${{ github.event.number }} PR_NUM: ${{ github.event.number }}
run: echo $PR_NUM > pr_num.txt run: echo $PR_NUM > pr_num.txt
- name: Upload PR number - name: Upload PR number
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@v4
with: with:
name: pr_number name: pr_number
path: ./pr_num.txt path: ./pr_num.txt

View file

@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Report success - name: Report success
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 uses: actions/github-script@v7
with: with:
script: | script: |
const owner = '${{ github.repository_owner }}'; const owner = '${{ github.repository_owner }}';
@ -43,7 +43,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Report pending - name: Report pending
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 uses: actions/github-script@v7
with: with:
script: | script: |
const owner = '${{ github.repository_owner }}'; const owner = '${{ github.repository_owner }}';

View file

@ -6,7 +6,7 @@ on:
branches: branches:
- master - master
pull_request: pull_request:
types: [opened, reopened, synchronize, labeled] types: [opened, reopened, synchronize, labeled, unlabeled]
concurrency: concurrency:
group: pre-commit-${{github.event.pull_request.number || github.ref}} group: pre-commit-${{github.event.pull_request.number || github.ref}}
@ -15,29 +15,21 @@ concurrency:
jobs: jobs:
lint: lint:
if: | if: |
github.event_name != 'pull_request' ||
contains(github.event.pull_request.labels.*.name, 'Status: Pending Merge') || contains(github.event.pull_request.labels.*.name, 'Status: Pending Merge') ||
contains(github.event.pull_request.labels.*.name, 'Re-trigger Pre-commit Hooks') github.event_name != 'pull_request'
name: Check if fixes are needed name: Check if fixes are needed
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout latest commit - name: Checkout latest commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
fetch-depth: 2 fetch-depth: 2
- name: Remove Label
if: contains(github.event.pull_request.labels.*.name, 'Re-trigger Pre-commit Hooks')
run: gh pr edit ${{ github.event.number }} --remove-label 'Re-trigger Pre-commit Hooks'
env:
GH_TOKEN: ${{ github.token }}
- name: Set up Python 3 - name: Set up Python 3
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 uses: actions/setup-python@v5
with: with:
cache-dependency-path: tools/pre-commit/requirements.txt cache-dependency-path: tools/pre-commit/requirements.txt
cache: "pip" cache: 'pip'
python-version: "3.x" python-version: "3.x"
- name: Get Python version hash - name: Get Python version hash
@ -46,7 +38,7 @@ jobs:
echo "PY_HASH=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV echo "PY_HASH=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
- name: Restore pre-commit cache - name: Restore pre-commit cache
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache/restore@v4
id: restore-cache id: restore-cache
with: with:
path: | path: |
@ -58,13 +50,13 @@ jobs:
- name: Get changed files - name: Get changed files
id: changed-files id: changed-files
uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1 uses: tj-actions/changed-files@v42.0.2
- name: Run pre-commit hooks in changed files - name: Run pre-commit hooks in changed files
run: pre-commit run --color=always --show-diff-on-failure --files ${{ steps.changed-files.outputs.all_changed_files }} run: pre-commit run --color=always --show-diff-on-failure --files ${{ steps.changed-files.outputs.all_changed_files }}
- name: Save pre-commit cache - name: Save pre-commit cache
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache/save@v4
if: ${{ always() && steps.restore-cache.outputs.cache-hit != 'true' }} if: ${{ always() && steps.restore-cache.outputs.cache-hit != 'true' }}
continue-on-error: true continue-on-error: true
with: with:
@ -73,7 +65,7 @@ jobs:
key: ${{ steps.restore-cache.outputs.cache-primary-key }} key: ${{ steps.restore-cache.outputs.cache-primary-key }}
- name: Push changes using pre-commit-ci-lite - name: Push changes using pre-commit-ci-lite
uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0 uses: pre-commit-ci/lite-action@v1.0.2
# Only push changes in PRs # Only push changes in PRs
if: ${{ always() && github.event_name == 'pull_request' }} if: ${{ always() && github.event_name == 'pull_request' }}
with: with:

View file

@ -44,12 +44,12 @@ jobs:
- name: Read the pr_num file - name: Read the pr_num file
id: pr_num_reader id: pr_num_reader
uses: juliangruber/read-file-action@b549046febe0fe86f8cb4f93c24e284433f9ab58 # v1.1.7 uses: juliangruber/read-file-action@v1
with: with:
path: ./artifacts/workflows/pr_num.txt path: ./artifacts/workflows/pr_num.txt
- name: Report results - name: Report results
uses: P-R-O-C-H-Y/report-size-deltas@256d1f13e4195cd7fd436d2f959e6dc4d5e4b406 # libs uses: P-R-O-C-H-Y/report-size-deltas@libs
with: with:
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
github-token: ${{ env.GITHUB_TOKEN }} github-token: ${{ env.GITHUB_TOKEN }}

View file

@ -11,11 +11,11 @@ env:
jobs: jobs:
sizes-test-results: sizes-test-results:
name: Sizes Comparison Results name: Sizes Comparsion Results
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout gh-pages branch - name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4 # This step checks out the repository's code at gh-pages branch
with: with:
ref: gh-pages ref: gh-pages
@ -34,14 +34,15 @@ jobs:
mv v2.x_cli_compile/*.json artifacts/sizes-report/master/ mv v2.x_cli_compile/*.json artifacts/sizes-report/master/
- name: Report results - name: Report results
uses: P-R-O-C-H-Y/report-size-deltas@2043188c68f483a7b50527c4eacf609d05bb67a5 # sizes_v2 uses: P-R-O-C-H-Y/report-size-deltas@sizes_v2
with: with:
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
github-token: ${{ env.GITHUB_TOKEN }} github-token: ${{ env.GITHUB_TOKEN }}
destination-file: ${{ env.RESULT_SIZES_TEST_FILE }} destination-file: ${{ env.RESULT_SIZES_TEST_FILE }}
- name: Append file with action URL - name: Append file with action URL
run: echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_SIZES_TEST_FILE }} run:
echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_SIZES_TEST_FILE }}
- name: Push to github repo - name: Push to github repo
run: | run: |

View file

@ -14,15 +14,15 @@ env:
jobs: jobs:
sizes-test-results: sizes-test-results:
name: Sizes Comparison Results name: Sizes Comparsion Results
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: | if: |
github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success' github.event.workflow_run.conclusion == 'success'
steps: steps:
- name: Checkout gh-pages branch - name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4 # This step checks out the repository's code at gh-pages branch
with: with:
ref: gh-pages ref: gh-pages
@ -44,29 +44,28 @@ jobs:
gh api "$artifacts_url" -q '.artifacts[] | [.name, .archive_download_url] | @tsv' | while read artifact gh api "$artifacts_url" -q '.artifacts[] | [.name, .archive_download_url] | @tsv' | while read artifact
do do
IFS=$'\t' read name url <<< "$artifact" IFS=$'\t' read name url <<< "$artifact"
# Only process pr_number and pr_cli_compile artifacts gh api $url > "$name.zip"
if [[ "$name" == "pr_number" || "$name" =~ ^pr_cli_compile_[0-9]+$ ]]; then unzip -j "$name.zip" -d "temp_$name"
gh api $url > "$name.zip" if [[ "$name" == "pr_number" ]]; then
unzip -o -j "$name.zip" -d "temp_$name" mv "temp_$name"/* sizes-report
if [[ "$name" == "pr_number" ]]; then elif [[ "$name" == "pr_cli"* ]]; then
mv "temp_$name"/* sizes-report mv "temp_$name"/* sizes-report/pr
elif [[ "$name" =~ ^pr_cli_compile_[0-9]+$ ]]; then else
mv "temp_$name"/* sizes-report/pr mv "temp_$name"/* sizes-report
fi
rm -r "temp_$name"
fi fi
rm -r "temp_$name"
done done
echo "Contents of parent directory:" echo "Contents of parent directory:"
ls -R .. ls -R ..
- name: Read the pr_num file - name: Read the pr_num file
id: pr_num_reader id: pr_num_reader
uses: juliangruber/read-file-action@b549046febe0fe86f8cb4f93c24e284433f9ab58 # v1.1.7 uses: juliangruber/read-file-action@v1
with: with:
path: ./artifacts/sizes-report/pr_num.txt path: ./artifacts/sizes-report/pr_num.txt
- name: Report results - name: Report results
uses: P-R-O-C-H-Y/report-size-deltas@bea91d2c99ca80c88a883b39b1c4012f00ec3d09 # sizes_v2 uses: P-R-O-C-H-Y/report-size-deltas@sizes_v2
with: with:
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
github-token: ${{ env.GITHUB_TOKEN }} github-token: ${{ env.GITHUB_TOKEN }}

View file

@ -2,57 +2,31 @@ name: Compilation Tests
on: on:
workflow_dispatch: workflow_dispatch:
inputs:
log_level:
description: "Log level"
default: "none"
type: "choice"
required: true
options:
- "none"
- "error"
- "warn"
- "info"
- "debug"
- "verbose"
schedule:
# Every Sunday at 2:00 UTC run a build with verbose log level
- cron: "0 2 * * SUN"
push: push:
branches: branches:
- master - master
- release/* - release/v2.x
pull_request: pull_request:
paths: paths:
- "cores/**" - 'cores/**'
- "libraries/**" - 'libraries/**'
- "!libraries/**.md" - '!libraries/**.md'
- "!libraries/**.txt" - '!libraries/**.txt'
- "!libraries/**.properties" - '!libraries/**.properties'
- "!libraries/**.py" - '!libraries/**.py'
- "package/**" - 'package/**'
- "idf_component_examples/**" - 'tools/**.py'
- "tools/**.py" - 'platform.txt'
- "platform.txt" - 'programmers.txt'
- "programmers.txt" - 'idf_component.yml'
- "idf_component.yml" - 'Kconfig.projbuild'
- "Kconfig.projbuild" - 'package.json'
- "package.json" - '.github/workflows/push.yml'
- "CMakeLists.txt" - '.github/scripts/**'
- ".github/workflows/push.yml" - '!.github/scripts/find_*'
- ".github/scripts/**" - '!.github/scripts/on-release.sh'
- "!.github/scripts/find_*" - '!.github/scripts/tests_*'
- "!.github/scripts/on-release.sh" - '!.github/scripts/upload_*'
- "!.github/scripts/tests_*"
- "!.github/scripts/upload_*"
- "variants/esp32/**/*"
- "variants/esp32c3/**/*"
- "variants/esp32c5/**/*"
- "variants/esp32c6/**/*"
- "variants/esp32h2/**/*"
- "variants/esp32p4/**/*"
- "variants/esp32s2/**/*"
- "variants/esp32s3/**/*"
concurrency: concurrency:
group: build-${{github.event.pull_request.number || github.ref}} group: build-${{github.event.pull_request.number || github.ref}}
@ -65,47 +39,41 @@ jobs:
cmake-check: cmake-check:
name: Check cmake file name: Check cmake file
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) }}
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- run: bash ./.github/scripts/check-cmakelists.sh - run: bash ./.github/scripts/check-cmakelists.sh
gen-chunks: gen-chunks:
name: Generate chunks name: Generate chunks
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) }}
outputs: outputs:
build_all: ${{ steps.set-chunks.outputs.build_all }} build_all: ${{ steps.set-chunks.outputs.build_all }}
build_libraries: ${{ steps.set-chunks.outputs.build_libraries }} build_libraries: ${{ steps.set-chunks.outputs.build_libraries }}
build_static_sketches: ${{ steps.set-chunks.outputs.build_static_sketches }} build_static_sketches: ${{ steps.set-chunks.outputs.build_static_sketches }}
build_idf: ${{ steps.set-chunks.outputs.build_idf }} build_idf: ${{ steps.set-chunks.outputs.build_idf }}
build_platformio: ${{ steps.set-chunks.outputs.build_platformio }}
chunk_count: ${{ steps.set-chunks.outputs.chunk_count }} chunk_count: ${{ steps.set-chunks.outputs.chunk_count }}
chunks: ${{ steps.set-chunks.outputs.chunks }} chunks: ${{ steps.set-chunks.outputs.chunks }}
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
fetch-depth: 2 fetch-depth: 2
- name: Get changed files - name: Get changed files
id: changed-files id: changed-files
uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1 uses: tj-actions/changed-files@v44
with: with:
files_yaml: | files_yaml: |
core: core:
- '.github/**' - '.github/**'
- '!.github/scripts/install-platformio-esp32.sh'
- 'cores/**' - 'cores/**'
- 'package/**' - 'package/**'
- 'tools/**' - 'tools/**'
- '!tools/platformio-build.py'
- 'platform.txt' - 'platform.txt'
- 'programmers.txt' - 'programmers.txt'
- "variants/esp32/**/*"
- "variants/esp32c3/**/*"
- "variants/esp32c6/**/*"
- "variants/esp32h2/**/*"
- "variants/esp32p4/**/*"
- "variants/esp32s2/**/*"
- "variants/esp32s3/**/*"
libraries: libraries:
- 'libraries/**/examples/**' - 'libraries/**/examples/**'
- 'libraries/**/src/**' - 'libraries/**/src/**'
@ -124,33 +92,36 @@ jobs:
idf: idf:
- 'idf_component.yml' - 'idf_component.yml'
- 'Kconfig.projbuild' - 'Kconfig.projbuild'
- 'CMakeLists.txt' platformio:
- "idf_component_examples/**" - 'package.json'
- '.github/scripts/install-platformio-esp32.sh'
- 'tools/platformio-build.py'
- name: Set chunks - name: Set chunks
id: set-chunks id: set-chunks
env: env:
LIB_FILES: ${{ steps.changed-files.outputs.libraries_all_changed_files }} LIB_FILES: ${{ steps.changed-files.outputs.libraries_all_changed_files }}
IS_PR: ${{ github.event_name == 'pull_request' }} IS_PR: ${{ github.event_name == 'pull_request' }}
MAX_CHUNKS: ${{ env.MAX_CHUNKS }} MAX_CHUNKS: ${{ env.MAX_CHUNKS }}
BUILD_IDF: ${{ steps.changed-files.outputs.idf_any_changed == 'true' }} BUILD_PLATFORMIO: ${{ steps.changed-files.outputs.platformio_any_changed == 'true' }}
BUILD_LIBRARIES: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }} BUILD_IDF: ${{ steps.changed-files.outputs.idf_any_changed == 'true' }}
BUILD_STATIC_SKETCHES: ${{ steps.changed-files.outputs.static_sketeches_any_changed == 'true' }} BUILD_LIBRARIES: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }}
FS_CHANGED: ${{ steps.changed-files.outputs.fs_any_changed == 'true' }} BUILD_STATIC_SKETCHES: ${{ steps.changed-files.outputs.static_sketeches_any_changed == 'true' }}
NETWORKING_CHANGED: ${{ steps.changed-files.outputs.networking_any_changed == 'true' }} FS_CHANGED: ${{ steps.changed-files.outputs.fs_any_changed == 'true' }}
CORE_CHANGED: ${{ steps.changed-files.outputs.core_any_changed == 'true' }} NETWORKING_CHANGED: ${{ steps.changed-files.outputs.networking_any_changed == 'true' }}
LIB_CHANGED: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }} CORE_CHANGED: ${{ steps.changed-files.outputs.core_any_changed == 'true' }}
run: | LIB_CHANGED: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }}
bash ./.github/scripts/set_push_chunks.sh run: |
bash ./.github/scripts/set_push_chunks.sh
- name: Upload sketches found - name: Upload sketches found
if: ${{ steps.set-chunks.outputs.build_all == 'false' && steps.set-chunks.outputs.build_libraries == 'true' }} if: ${{ steps.set-chunks.outputs.build_all == 'false' && steps.set-chunks.outputs.build_libraries == 'true' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@v4
with: with:
name: sketches_found name: sketches_found
path: sketches_found.txt path: sketches_found.txt
overwrite: true overwrite: true
if-no-files-found: error if-no-files-found: error
# Ubuntu # Ubuntu
build-arduino-linux: build-arduino-linux:
@ -164,55 +135,45 @@ jobs:
chunk: ${{ fromJson(needs.gen-chunks.outputs.chunks) }} chunk: ${{ fromJson(needs.gen-chunks.outputs.chunks) }}
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 - uses: actions/setup-python@v5
with: with:
python-version: "3.x" python-version: '3.x'
- name: Get libs cache - name: Get libs cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache@v4
with: with:
key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }} key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }}
path: | path: |
./tools/dist ./tools/dist
./tools/esp32-arduino-libs ./tools/esp32-arduino-libs
./tools/esptool ./tools/esptool
./tools/mk* ./tools/mk*
./tools/openocd-esp32 ./tools/openocd-esp32
./tools/riscv32-* ./tools/riscv32-*
./tools/xtensa-* ./tools/xtensa-*
- name: Set Log Level - name: Build all sketches
run: | if: ${{ needs.gen-chunks.outputs.build_all == 'true' }}
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ env.MAX_CHUNKS }} 1
echo "LOG_LEVEL=${{ github.event.inputs.log_level }}" >> $GITHUB_ENV
elif [ "${{ github.event_name }}" == "schedule" ]; then
echo "LOG_LEVEL=verbose" >> $GITHUB_ENV
else
echo "LOG_LEVEL=none" >> $GITHUB_ENV
fi
- name: Build all sketches - name: Download sketches found
if: ${{ needs.gen-chunks.outputs.build_all == 'true' }} if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }}
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ env.MAX_CHUNKS }} 1 ${{ env.LOG_LEVEL }} uses: actions/download-artifact@v4
with:
name: sketches_found
- name: Download sketches found - name: Build selected sketches
if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }} if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }}
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ needs.gen-chunks.outputs.chunk_count }} 1 sketches_found.txt
with:
name: sketches_found
- name: Build selected sketches #Upload cli compile json as artifact
if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }} - name: Upload cli compile json
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ needs.gen-chunks.outputs.chunk_count }} 1 ${{ env.LOG_LEVEL }} sketches_found.txt uses: actions/upload-artifact@v4
with:
#Upload cli compile json as artifact name: pr_cli_compile_${{ matrix.chunk }}
- name: Upload cli compile json path: cli_compile_${{ matrix.chunk }}.json
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 overwrite: true
with:
name: pr_cli_compile_${{ matrix.chunk }}
path: cli_compile_${{ matrix.chunk }}.json
overwrite: true
# Windows and MacOS # Windows and MacOS
build-arduino-win-mac: build-arduino-win-mac:
@ -226,12 +187,34 @@ jobs:
os: [windows-latest, macOS-latest] os: [windows-latest, macOS-latest]
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 - uses: actions/setup-python@v5
with: with:
python-version: "3.x" python-version: '3.x'
- name: Build Sketches - name: Build Sketches
run: bash ./.github/scripts/on-push.sh run: bash ./.github/scripts/on-push.sh
# PlatformIO on Windows, Ubuntu and Mac
build-platformio:
name: PlatformIO on ${{ matrix.os }}
needs: gen-chunks
if: |
needs.gen-chunks.outputs.build_all == 'true' ||
needs.gen-chunks.outputs.build_static_sketches == 'true' ||
needs.gen-chunks.outputs.build_platformio == 'true'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Build Sketches
run: bash ./.github/scripts/on-push.sh 1 1 #equal and non-zero to trigger PIO
build-esp-idf-component: build-esp-idf-component:
name: Build with ESP-IDF ${{ matrix.idf_ver }} for ${{ matrix.idf_target }} name: Build with ESP-IDF ${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
@ -240,7 +223,7 @@ jobs:
needs.gen-chunks.outputs.build_all == 'true' || needs.gen-chunks.outputs.build_all == 'true' ||
needs.gen-chunks.outputs.build_libraries == 'true' || needs.gen-chunks.outputs.build_libraries == 'true' ||
needs.gen-chunks.outputs.build_idf == 'true' needs.gen-chunks.outputs.build_idf == 'true'
runs-on: ubuntu-latest runs-on: ubuntu-20.04
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -248,43 +231,24 @@ jobs:
# See https://hub.docker.com/r/espressif/idf/tags and # See https://hub.docker.com/r/espressif/idf/tags and
# https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-docker-image.html # https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-docker-image.html
# for details. # for details.
idf_ver: ["release-v5.3","release-v5.4","release-v5.5"] idf_ver: ["release-v5.1"]
idf_target: idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2"]
[
"esp32",
"esp32s2",
"esp32s3",
"esp32c2",
"esp32c3",
"esp32c6",
"esp32h2",
"esp32p4"
]
container: espressif/idf:${{ matrix.idf_ver }} container: espressif/idf:${{ matrix.idf_ver }}
steps: steps:
- name: Check out arduino-esp32 as a component - name: Check out arduino-esp32 as a component
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
path: components/arduino-esp32 path: components/arduino-esp32
- name: Setup jq
uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1
- name: Build - name: Build
env: env:
IDF_TARGET: ${{ matrix.idf_target }} IDF_TARGET: ${{ matrix.idf_target }}
shell: bash shell: bash
run: | run: |
chmod a+x ./components/arduino-esp32/.github/scripts/* . ${IDF_PATH}/export.sh
./components/arduino-esp32/.github/scripts/on-push-idf.sh idf.py create-project test
echo CONFIG_FREERTOS_HZ=1000 > test/sdkconfig.defaults
- name: Upload generated sdkconfig files for debugging idf.py -C test -DEXTRA_COMPONENT_DIRS=$PWD/components build
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: always()
with:
name: sdkconfig-${{ matrix.idf_ver }}-${{ matrix.idf_target }}
path: ./components/arduino-esp32/idf_component_examples/**/sdkconfig
# Save artifacts to gh-pages # Save artifacts to gh-pages
save-master-artifacts: save-master-artifacts:
@ -293,18 +257,19 @@ jobs:
if: github.event_name == 'push' && github.ref == 'refs/heads/master' if: github.event_name == 'push' && github.ref == 'refs/heads/master'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
# Check out repository # Check out repository
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
token: ${{secrets.GITHUB_TOKEN}} token: ${{secrets.GITHUB_TOKEN}}
fetch-depth: "0" fetch-depth: '0'
- name: Switch branch - name: Switch branch
run: git checkout remotes/origin/gh-pages run:
git checkout remotes/origin/gh-pages
- name: Download sketches reports artifact - name: Download sketches reports artifact
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 uses: actions/download-artifact@v4
with: with:
pattern: pr_cli_compile_* pattern: pr_cli_compile_*
merge-multiple: true merge-multiple: true
@ -326,7 +291,7 @@ jobs:
#Upload PR number as artifact #Upload PR number as artifact
upload-pr-number: upload-pr-number:
name: Upload PR number name: Upload PR number
if: ${{ github.event_name == 'pull_request' && !startsWith(github.head_ref, 'release/') }} if: github.event_name == 'pull_request'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Save the PR number in an artifact - name: Save the PR number in an artifact
@ -334,9 +299,8 @@ jobs:
env: env:
PR_NUM: ${{ github.event.number }} PR_NUM: ${{ github.event.number }}
run: echo $PR_NUM > pr_num.txt run: echo $PR_NUM > pr_num.txt
- name: Upload PR number - name: Upload PR number
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@v4
with: with:
name: pr_number name: pr_number
path: ./pr_num.txt path: ./pr_num.txt

View file

@ -10,23 +10,15 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with:
with: fetch-depth: 0
fetch-depth: 0 - uses: actions/setup-python@v5
with:
- name: Set up Python python-version: '3.x'
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 - run: pip install packaging
with: - run: pip install pyserial
python-version: "3.x" - name: Build Release
env:
- name: Install packaging GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: pip install packaging run: bash ./.github/scripts/on-release.sh
- name: Install pyserial
run: pip install pyserial
- name: Build Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash ./.github/scripts/on-release.sh

View file

@ -16,22 +16,23 @@ on:
pull_request: pull_request:
types: [opened, reopened, closed, synchronize, labeled, unlabeled] types: [opened, reopened, closed, synchronize, labeled, unlabeled]
paths: paths:
- ".github/workflows/tests*" - '.github/workflows/tests*'
- ".github/scripts/*.sh" - '.github/scripts/*.sh'
- "!.github/scripts/check-cmakelists.sh" - '!.github/scripts/check-cmakelists.sh'
- "!.github/scripts/find_*" - '!.github/scripts/find_*'
- "!.github/scripts/on-*.sh" - '!.github/scripts/on-*.sh'
- "!.github/scripts/set_push_chunks.sh" - '!.github/scripts/set_push_chunks.sh'
- "!.github/scripts/update-version.sh" - '!.github/scripts/update-version.sh'
- "!.github/scripts/upload_py_tools.sh" - '!.github/scripts/upload_py_tools.sh'
- "tests/**" - 'tests/**'
- "cores/**" - 'cores/**'
- "libraries/*/src/**.cpp" - 'libraries/**'
- "libraries/*/src/**.h" - '!libraries/**.md'
- "libraries/*/src/**.c" - '!libraries/**.txt'
- "package/**" - '!libraries/**.properties'
- 'package/**'
schedule: schedule:
- cron: "0 2 * * *" - cron: '0 2 * * *'
concurrency: concurrency:
group: tests-${{ github.event.pull_request.number || github.ref }} group: tests-${{ github.event.pull_request.number || github.ref }}
@ -43,7 +44,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Upload - name: Upload
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@v4
with: with:
name: event_file name: event_file
path: ${{ github.event_path }} path: ${{ github.event_path }}
@ -56,25 +57,29 @@ jobs:
hw-types: ${{ steps.set-matrix.outputs.hw-types }} hw-types: ${{ steps.set-matrix.outputs.hw-types }}
wokwi-types: ${{ steps.set-matrix.outputs.wokwi-types }} wokwi-types: ${{ steps.set-matrix.outputs.wokwi-types }}
qemu-types: ${{ steps.set-matrix.outputs.qemu-types }} qemu-types: ${{ steps.set-matrix.outputs.qemu-types }}
targets: ${{ steps.set-matrix.outputs.targets }}
env:
IS_PR: ${{ github.event.pull_request.number != null }}
PERFORMANCE_ENABLED: ${{ contains(github.event.pull_request.labels.*.name, 'perf_test') }}
steps: steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .github/scripts/tests_matrix.sh
- name: Set matrix - name: Set matrix
id: set-matrix id: set-matrix
run: bash .github/scripts/tests_matrix.sh run: |
build_types='["validation"'
hw_types='["validation"'
wokwi_types='["validation"'
qemu_types='["validation"'
- name: Upload is_pr=${{ github.event.pull_request.number != null }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 is_performance_enabled=${{ contains(github.event.pull_request.labels.*.name, 'perf_test') }}
with:
name: matrix_info if [[ $is_pr != 'true' ]] || [[ $is_performance_enabled == 'true' ]]; then
path: info/* build_types+=',"performance"'
hw_types+=',"performance"'
#wokwi_types+=',"performance"'
#qemu_types+=',"performance"'
fi
echo "build-types=$build_types]" >> $GITHUB_OUTPUT
echo "hw-types=$hw_types]" >> $GITHUB_OUTPUT
echo "wokwi-types=$wokwi_types]" >> $GITHUB_OUTPUT
echo "qemu-types=$qemu_types]" >> $GITHUB_OUTPUT
call-build-tests: call-build-tests:
name: Build name: Build
@ -83,7 +88,7 @@ jobs:
strategy: strategy:
matrix: matrix:
type: ${{ fromJson(needs.gen-matrix.outputs.build-types) }} type: ${{ fromJson(needs.gen-matrix.outputs.build-types) }}
chip: ${{ fromJson(needs.gen-matrix.outputs.targets) }} chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2']
with: with:
type: ${{ matrix.type }} type: ${{ matrix.type }}
chip: ${{ matrix.chip }} chip: ${{ matrix.chip }}
@ -100,7 +105,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
type: ${{ fromJson(needs.gen-matrix.outputs.hw-types) }} type: ${{ fromJson(needs.gen-matrix.outputs.hw-types) }}
chip: ${{ fromJson(needs.gen-matrix.outputs.targets) }} chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2']
with: with:
type: ${{ matrix.type }} type: ${{ matrix.type }}
chip: ${{ matrix.chip }} chip: ${{ matrix.chip }}
@ -115,7 +120,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
type: ${{ fromJson(needs.gen-matrix.outputs.qemu-types) }} type: ${{ fromJson(needs.gen-matrix.outputs.qemu-types) }}
chip: ["esp32", "esp32c3"] chip: ['esp32', 'esp32c3']
with: with:
type: ${{ matrix.type }} type: ${{ matrix.type }}
chip: ${{ matrix.chip }} chip: ${{ matrix.chip }}

View file

@ -5,11 +5,11 @@ on:
inputs: inputs:
type: type:
type: string type: string
description: "Type of tests to build" description: 'Type of tests to build'
required: true required: true
chip: chip:
type: string type: string
description: "Chip to build tests for" description: 'Chip to build tests for'
required: true required: true
jobs: jobs:
@ -22,14 +22,13 @@ jobs:
- name: Check if already built - name: Check if already built
id: cache-build-binaries id: cache-build-binaries
if: github.event.pull_request.number != null if: github.event.pull_request.number != null
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache/restore@v4
with: with:
key: tests-${{ env.id }}-bin key: tests-${{ env.id }}-bin
path: | path: |
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin ~/.arduino/tests/**/build*.tmp/*.bin
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf ~/.arduino/tests/**/build*.tmp/*.elf
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json ~/.arduino/tests/**/build*.tmp/*.json
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig
- name: Evaluate if tests should be built - name: Evaluate if tests should be built
id: check-build id: check-build
@ -46,10 +45,10 @@ jobs:
- name: Checkout user repository - name: Checkout user repository
if: ${{ steps.check-build.outputs.enabled == 'true' }} if: ${{ steps.check-build.outputs.enabled == 'true' }}
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
- name: Get libs cache - name: Get libs cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache@v4
if: ${{ steps.check-build.outputs.enabled == 'true' }} if: ${{ steps.check-build.outputs.enabled == 'true' }}
with: with:
key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }} key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }}
@ -68,23 +67,21 @@ jobs:
bash .github/scripts/tests_build.sh -c -type ${{ inputs.type }} -t ${{ inputs.chip }} bash .github/scripts/tests_build.sh -c -type ${{ inputs.type }} -t ${{ inputs.chip }}
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} binaries as cache - name: Upload ${{ inputs.chip }} ${{ inputs.type }} binaries as cache
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache/save@v4
if: steps.check-build.outputs.enabled == 'true' && github.event.pull_request.number != null if: steps.check-build.outputs.enabled == 'true' && github.event.pull_request.number != null
with: with:
key: tests-${{ env.id }}-bin key: tests-${{ env.id }}-bin
path: | path: |
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin ~/.arduino/tests/**/build*.tmp/*.bin
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf ~/.arduino/tests/**/build*.tmp/*.elf
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json ~/.arduino/tests/**/build*.tmp/*.json
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} binaries as artifacts - name: Upload ${{ inputs.chip }} ${{ inputs.type }} binaries as artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@v4
with: with:
name: tests-bin-${{ inputs.chip }}-${{ inputs.type }} name: tests-bin-${{ inputs.chip }}-${{ inputs.type }}
overwrite: true overwrite: true
path: | path: |
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin ~/.arduino/tests/**/build*.tmp/*.bin
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf ~/.arduino/tests/**/build*.tmp/*.elf
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json ~/.arduino/tests/**/build*.tmp/*.json
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig

View file

@ -5,11 +5,11 @@ on:
inputs: inputs:
type: type:
type: string type: string
description: "Type of tests to run" description: 'Type of tests to run'
required: true required: true
chip: chip:
type: string type: string
description: "Chip to run tests for" description: 'Chip to run tests for'
required: true required: true
env: env:
@ -22,22 +22,17 @@ defaults:
jobs: jobs:
hardware-test: hardware-test:
name: Hardware ${{ inputs.chip }} ${{ inputs.type }} tests name: Hardware ${{ inputs.chip }} ${{ inputs.type }} tests
runs-on: ["arduino", "${{ inputs.chip }}"] runs-on: [arduino, "${{ inputs.chip }}"]
env: env:
id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }} id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }}
container: container:
image: python:3.10.1-bullseye image: python:3.10.1-bullseye
options: --privileged --device-cgroup-rule="c 188:* rmw" --device-cgroup-rule="c 166:* rmw" options: --privileged
steps: steps:
- name: Clean workspace
run: |
rm -rf ./*
rm -rf ~/.arduino/tests
- name: Check if already passed - name: Check if already passed
id: cache-results id: cache-results
if: github.event.pull_request.number != null if: github.event.pull_request.number != null
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache/restore@v4
with: with:
key: tests-${{ env.id }}-results-hw key: tests-${{ env.id }}-results-hw
path: | path: |
@ -59,13 +54,17 @@ jobs:
- name: Checkout user repository - name: Checkout user repository
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
sparse-checkout: | sparse-checkout: |
* *
- name: List files
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
run: ls -la
# setup-python currently only works on ubuntu images # setup-python currently only works on ubuntu images
# - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 # - uses: actions/setup-python@v5
# if: ${{ steps.check-tests.outputs.enabled == 'true' }} # if: ${{ steps.check-tests.outputs.enabled == 'true' }}
# with: # with:
# cache-dependency-path: tests/requirements.txt # cache-dependency-path: tests/requirements.txt
@ -82,16 +81,11 @@ jobs:
- name: Get binaries - name: Get binaries
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 uses: actions/download-artifact@v4
with: with:
name: tests-bin-${{ inputs.chip }}-${{ inputs.type }} name: tests-bin-${{ inputs.chip }}-${{ inputs.type }}
path: | path: |
~/.arduino/tests/${{ inputs.chip }} ~/.arduino/tests
- name: List binaries
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
run: |
ls -laR ~/.arduino/tests
- name: Run Tests - name: Run Tests
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
@ -99,7 +93,7 @@ jobs:
bash .github/scripts/tests_run.sh -c -type ${{ inputs.type }} -t ${{ inputs.chip }} -i 0 -m 1 -e 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 - name: Upload ${{ inputs.chip }} ${{ inputs.type }} hardware results as cache
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache/save@v4
if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null
with: with:
key: tests-${{ env.id }}-results-hw key: tests-${{ env.id }}-results-hw
@ -108,7 +102,7 @@ jobs:
tests/**/result_*.json tests/**/result_*.json
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} hardware results as artifacts - name: Upload ${{ inputs.chip }} ${{ inputs.type }} hardware results as artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@v4
if: always() if: always()
with: with:
name: tests-results-hw-${{ inputs.chip }}-${{ inputs.type }} name: tests-results-hw-${{ inputs.chip }}-${{ inputs.type }}

View file

@ -21,7 +21,7 @@ jobs:
- name: Check if already passed - name: Check if already passed
id: get-cache-results id: get-cache-results
if: github.event.pull_request.number != null if: github.event.pull_request.number != null
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache/restore@v4
with: with:
key: tests-${{ env.id }}-results-qemu key: tests-${{ env.id }}-results-qemu
path: | path: |
@ -43,7 +43,7 @@ jobs:
- name: Checkout user repository - name: Checkout user repository
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
ref: ${{ github.event.pull_request.head.sha || github.sha }} ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false persist-credentials: false
@ -60,12 +60,12 @@ jobs:
cd .github cd .github
curl https://codeload.github.com/${{ github.repository }}/tar.gz/master | tar -xz --strip=2 arduino-esp32-master/.github curl https://codeload.github.com/${{ github.repository }}/tar.gz/master | tar -xz --strip=2 arduino-esp32-master/.github
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 - uses: actions/setup-python@v5
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
with: with:
cache-dependency-path: tests/requirements.txt cache-dependency-path: tests/requirements.txt
cache: "pip" cache: 'pip'
python-version: "3.x" python-version: '3.x'
- name: Install Python dependencies - name: Install Python dependencies
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
@ -74,14 +74,14 @@ jobs:
pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi
- name: Install APT dependencies - name: Install APT dependencies
uses: awalsh128/cache-apt-pkgs-action@5902b33ae29014e6ca012c5d8025d4346556bd40 # v1.4.3 uses: awalsh128/cache-apt-pkgs-action@v1.4.2
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
with: with:
packages: libpixman-1-0 libnuma1 libglib2.0-0 libslirp0 libsdl2-2.0-0 packages: libpixman-1-0 libnuma1 libglib2.0-0 libslirp0 libsdl2-2.0-0
version: 1.0 version: 1.0
- name: Get QEMU version - name: Get QEMU version
uses: pozetroninc/github-action-get-latest-release@2a61c339ea7ef0a336d1daa35ef0cb1418e7676c # v0.8.0 uses: pozetroninc/github-action-get-latest-release@v0.7.0
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
id: get-qemu-version id: get-qemu-version
with: with:
@ -92,7 +92,7 @@ jobs:
- name: Cache QEMU - name: Cache QEMU
id: cache-qemu id: cache-qemu
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache@v4
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
with: with:
path: | path: |
@ -113,18 +113,18 @@ jobs:
- name: Get binaries - name: Get binaries
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 uses: actions/download-artifact@v4
with: with:
name: tests-bin-${{ inputs.chip }}-${{ inputs.type }} name: tests-bin-${{ inputs.chip }}-${{ inputs.type }}
path: | path: |
~/.arduino/tests/${{ inputs.chip }} ~/.arduino/tests
- name: Run Tests - name: Run Tests
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
run: QEMU_PATH="${{ env.QEMU_INSTALL_PATH }}" bash .github/scripts/tests_run.sh -c -type ${{inputs.type}} -t ${{inputs.chip}} -i 0 -m 1 -Q run: QEMU_PATH="${{ env.QEMU_INSTALL_PATH }}" bash .github/scripts/tests_run.sh -c -type ${{inputs.type}} -t ${{inputs.chip}} -i 0 -m 1 -Q
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} QEMU results as cache - name: Upload ${{ inputs.chip }} ${{ inputs.type }} QEMU results as cache
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache/save@v4
if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null
with: with:
key: tests-${{ env.id }}-results-qemu key: tests-${{ env.id }}-results-qemu
@ -133,7 +133,7 @@ jobs:
tests/**/result_*.json tests/**/result_*.json
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} QEMU results as artifacts - name: Upload ${{ inputs.chip }} ${{ inputs.type }} QEMU results as artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@v4
if: always() if: always()
with: with:
name: tests-results-qemu-${{ inputs.chip }}-${{ inputs.type }} name: tests-results-qemu-${{ inputs.chip }}-${{ inputs.type }}

View file

@ -18,18 +18,18 @@ jobs:
github.event.workflow_run.conclusion == 'timed_out' github.event.workflow_run.conclusion == 'timed_out'
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
actions: write actions: write
statuses: write statuses: write
checks: write checks: write
pull-requests: write pull-requests: write
contents: write contents: write
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
with: with:
ref: gh-pages ref: gh-pages
- name: Download and Extract Artifacts - name: Download and Extract Artifacts
uses: dawidd6/action-download-artifact@07ab29fd4a977ae4d2b275087cf67563dfdf0295 # v9 uses: dawidd6/action-download-artifact@v6
with: with:
run_id: ${{ github.event.workflow_run.id }} run_id: ${{ github.event.workflow_run.id }}
path: ./artifacts path: ./artifacts
@ -41,67 +41,26 @@ jobs:
original_sha=$(cat ./artifacts/parent-artifacts/sha.txt) original_sha=$(cat ./artifacts/parent-artifacts/sha.txt)
original_ref=$(cat ./artifacts/parent-artifacts/ref.txt) original_ref=$(cat ./artifacts/parent-artifacts/ref.txt)
original_conclusion=$(cat ./artifacts/parent-artifacts/conclusion.txt) original_conclusion=$(cat ./artifacts/parent-artifacts/conclusion.txt)
original_run_id=$(cat ./artifacts/parent-artifacts/run_id.txt)
# Sanitize the values to avoid security issues
# Event: Allow alphabetical characters and underscores
original_event=$(echo "$original_event" | tr -cd '[:alpha:]_')
# Action: Allow alphabetical characters and underscores
original_action=$(echo "$original_action" | tr -cd '[:alpha:]_')
# SHA: Allow alphanumeric characters
original_sha=$(echo "$original_sha" | tr -cd '[:alnum:]')
# Ref: Allow alphanumeric characters, slashes, underscores, dots, and dashes
original_ref=$(echo "$original_ref" | tr -cd '[:alnum:]/_.-')
# Conclusion: Allow alphabetical characters and underscores
original_conclusion=$(echo "$original_conclusion" | tr -cd '[:alpha:]_')
# Run ID: Allow numeric characters
original_run_id=$(echo "$original_run_id" | tr -cd '[:digit:]')
echo "original_event=$original_event" >> $GITHUB_ENV echo "original_event=$original_event" >> $GITHUB_ENV
echo "original_action=$original_action" >> $GITHUB_ENV echo "original_action=$original_action" >> $GITHUB_ENV
echo "original_sha=$original_sha" >> $GITHUB_ENV echo "original_sha=$original_sha" >> $GITHUB_ENV
echo "original_ref=$original_ref" >> $GITHUB_ENV echo "original_ref=$original_ref" >> $GITHUB_ENV
echo "original_conclusion=$original_conclusion" >> $GITHUB_ENV echo "original_conclusion=$original_conclusion" >> $GITHUB_ENV
echo "original_run_id=$original_run_id" >> $GITHUB_ENV
echo "original_event = $original_event" echo "original_event = $original_event"
echo "original_action = $original_action" echo "original_action = $original_action"
echo "original_sha = $original_sha" echo "original_sha = $original_sha"
echo "original_ref = $original_ref" echo "original_ref = $original_ref"
echo "original_conclusion = $original_conclusion" echo "original_conclusion = $original_conclusion"
echo "original_run_id = $original_run_id"
- name: Print links to other runs
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 }}"
- name: Publish Unit Test Results - name: Publish Unit Test Results
uses: EnricoMi/publish-unit-test-result-action@170bf24d20d201b842d7a52403b73ed297e6645b # v2.18.0 uses: EnricoMi/publish-unit-test-result-action@v2
with: with:
commit: ${{ env.original_sha }} commit: ${{ env.original_sha }}
event_file: ./artifacts/parent-artifacts/event_file/event.json event_file: ./artifacts/parent-artifacts/event_file/event.json
event_name: ${{ env.original_event }} event_name: ${{ env.original_event }}
files: ./artifacts/**/*.xml files: ./artifacts/**/*.xml
action_fail: true action_fail: 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() }}
with:
name: unity_results
overwrite: true
path: |
./unity_results.json
- name: Fail if tests failed - 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: ${{ env.original_conclusion == 'failure' || env.original_conclusion == 'timed_out' || github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'timed_out' }}
@ -109,13 +68,13 @@ jobs:
- name: Clean up caches - name: Clean up caches
if: always() if: always()
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 uses: actions/github-script@v7
with: with:
script: | script: |
const ref = process.env.original_ref; const ref = '${{ env.original_ref }}';
const key_prefix = 'tests-' + ref + '-'; const key_prefix = 'tests-' + ref + '-';
if (process.env.original_event == 'pull_request' && process.env.original_action != 'closed') { if ('${{ env.original_event }}' == 'pull_request' && '${{ env.original_action }}' != 'closed') {
console.log('Skipping cache cleanup for open PR'); console.log('Skipping cache cleanup for open PR');
return; return;
} }
@ -139,18 +98,18 @@ jobs:
}); });
- name: Report conclusion - name: Report conclusion
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 uses: actions/github-script@v7
if: always() if: always()
with: with:
script: | script: |
const owner = '${{ github.repository_owner }}'; const owner = '${{ github.repository_owner }}';
const repo = '${{ github.repository }}'.split('/')[1]; const repo = '${{ github.repository }}'.split('/')[1];
const sha = process.env.original_sha; const sha = '${{ env.original_sha }}';
core.debug(`owner: ${owner}`); core.debug(`owner: ${owner}`);
core.debug(`repo: ${repo}`); core.debug(`repo: ${repo}`);
core.debug(`sha: ${sha}`); core.debug(`sha: ${sha}`);
const { context: name, state } = (await github.rest.repos.createCommitStatus({ 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 (${{ env.original_event }} -> workflow_run -> workflow_run)',
owner: owner, owner: owner,
repo: repo, repo: repo,
sha: sha, sha: sha,
@ -160,36 +119,28 @@ jobs:
})).data; })).data;
core.info(`${name} is ${state}`); core.info(`${name} is ${state}`);
- name: Generate report - name: Create output folder
if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }}
env:
REPORT_FILE: ./runtime-tests-results/RUNTIME_TESTS_REPORT.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' }}
run: | run: |
rm -rf artifacts $REPORT_FILE rm -rf artifacts
mv -f ./unity_results.json ./runtime-tests-results/unity_results.json mkdir -p runtime-tests-results
touch $REPORT_FILE
python3 ./runtime-tests-results/table_generator.py ./runtime-tests-results/unity_results.json >> $REPORT_FILE
- name: Generate badge - name: Generate badge
if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }}
uses: jaywcjlove/generated-badges@0e078ae4d4bab3777ea4f137de496ab44688f5ad # v1.0.13 uses: jaywcjlove/generated-badges@v1.0.13
with: with:
label: Runtime Tests label: Runtime Tests
status: ${{ job.status == 'success' && 'passing' || 'failing' }} status: ${{ job.status }}
output: runtime-tests-results/badge.svg output: runtime-tests-results/badge.svg
color: ${{ job.status == 'success' && 'green' || 'red' }} color: ${{ job.status == 'success' && 'green' || 'red' }}
style: flat
- name: Push badge - name: Push badge
if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }}
run: | run: |
git config user.name "github-actions[bot]" git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
if [[ `git status --porcelain` ]]; then if [[ `git status --porcelain` ]]; then
git add --all git add --all
git commit -m "Updated runtime tests report" git commit -m "Updated runtime tests badge"
git push origin HEAD:gh-pages git push origin HEAD:gh-pages
fi fi

View file

@ -22,12 +22,9 @@ jobs:
outputs: outputs:
pr_num: ${{ steps.set-ref.outputs.pr_num }} pr_num: ${{ steps.set-ref.outputs.pr_num }}
ref: ${{ steps.set-ref.outputs.ref }} ref: ${{ steps.set-ref.outputs.ref }}
base: ${{ steps.set-ref.outputs.base }}
targets: ${{ steps.set-ref.outputs.targets }}
types: ${{ steps.set-ref.outputs.types }}
steps: steps:
- name: Report pending - name: Report pending
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 uses: actions/github-script@v7
with: with:
script: | script: |
const owner = '${{ github.repository_owner }}'; const owner = '${{ github.repository_owner }}';
@ -47,25 +44,17 @@ jobs:
core.info(`${name} is ${state}`); core.info(`${name} is ${state}`);
- name: Download and extract event file - name: Download and extract event file
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 uses: actions/download-artifact@v4
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }} run-id: ${{ github.event.workflow_run.id }}
name: event_file name: event_file
path: artifacts/event_file path: artifacts/event_file
- name: Download and extract matrix info
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
name: matrix_info
path: artifacts/matrix_info
- name: Try to read PR number - name: Try to read PR number
id: set-ref id: set-ref
run: | run: |
pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json | tr -cd "[:digit:]") pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)
if [ -z "$pr_num" ] || [ "$pr_num" == "null" ]; then if [ -z "$pr_num" ] || [ "$pr_num" == "null" ]; then
pr_num="" pr_num=""
fi fi
@ -75,22 +64,11 @@ jobs:
ref=${{ github.ref }} ref=${{ github.ref }}
fi fi
action=$(jq -r '.action' artifacts/event_file/event.json | tr -cd "[:alpha:]_") action=$(jq -r '.action' artifacts/event_file/event.json)
if [ "$action" == "null" ]; then if [ "$action" == "null" ]; then
action="" action=""
fi fi
base=$(jq -r '.pull_request.base.ref' artifacts/event_file/event.json | tr -cd "[:alnum:]/_.-")
if [ -z "$base" ] || [ "$base" == "null" ]; then
base=${{ github.ref }}
fi
types=$(cat artifacts/matrix_info/wokwi_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 "pr_num = $pr_num" echo "pr_num = $pr_num"
printf "$ref" >> artifacts/ref.txt printf "$ref" >> artifacts/ref.txt
@ -109,10 +87,6 @@ jobs:
printf "\nAction = " printf "\nAction = "
cat artifacts/action.txt cat artifacts/action.txt
printf "${{ github.event.workflow_run.id }}" >> artifacts/run_id.txt
printf "\nRun ID = "
cat artifacts/run_id.txt
if [ -z "$ref" ] || [ "$ref" == "null" ]; then if [ -z "$ref" ] || [ "$ref" == "null" ]; then
echo "Failed to get PR number or ref" echo "Failed to get PR number or ref"
exit 1 exit 1
@ -124,13 +98,10 @@ jobs:
cat artifacts/conclusion.txt cat artifacts/conclusion.txt
echo "pr_num=$pr_num" >> $GITHUB_OUTPUT echo "pr_num=$pr_num" >> $GITHUB_OUTPUT
echo "base=$base" >> $GITHUB_OUTPUT
echo "targets=$targets" >> $GITHUB_OUTPUT
echo "types=$types" >> $GITHUB_OUTPUT
echo "ref=$ref" >> $GITHUB_OUTPUT echo "ref=$ref" >> $GITHUB_OUTPUT
- name: Download and extract parent hardware results - name: Download and extract parent hardware results
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 uses: actions/download-artifact@v4
continue-on-error: true continue-on-error: true
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
@ -140,7 +111,7 @@ jobs:
path: artifacts/results/hw path: artifacts/results/hw
- name: Download and extract parent QEMU results - name: Download and extract parent QEMU results
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 uses: actions/download-artifact@v4
continue-on-error: true continue-on-error: true
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
@ -150,14 +121,14 @@ jobs:
path: artifacts/results/qemu path: artifacts/results/qemu
- name: Upload parent artifacts - name: Upload parent artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@v4
with: with:
name: parent-artifacts name: parent-artifacts
path: artifacts path: artifacts
if-no-files-found: error if-no-files-found: error
- name: Report conclusion - name: Report conclusion
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 uses: actions/github-script@v7
if: always() if: always()
with: with:
script: | script: |
@ -193,11 +164,11 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
type: ${{ fromJson(needs.get-artifacts.outputs.types) }} type: ['validation']
chip: ${{ fromJson(needs.get-artifacts.outputs.targets) }} chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2']
steps: steps:
- name: Report pending - name: Report pending
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 uses: actions/github-script@v7
with: with:
script: | script: |
const owner = '${{ github.repository_owner }}'; const owner = '${{ github.repository_owner }}';
@ -219,7 +190,7 @@ jobs:
- name: Check if already passed - name: Check if already passed
id: get-cache-results id: get-cache-results
if: needs.get-artifacts.outputs.pr_num if: needs.get-artifacts.outputs.pr_num
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache/restore@v4
with: with:
key: tests-${{ env.id }}-results-wokwi key: tests-${{ env.id }}-results-wokwi
path: | path: |
@ -240,19 +211,16 @@ jobs:
echo "enabled=$enabled" >> $GITHUB_OUTPUT echo "enabled=$enabled" >> $GITHUB_OUTPUT
# Note that changes to the workflows and tests will only be picked up after the PR is merged # Note that changes to the workflows and tests will only be picked up after the PR is merged
# DO NOT CHECKOUT THE USER'S REPOSITORY IN THIS WORKFLOW. IT HAS HIGH SECURITY RISKS.
- name: Checkout repository - name: Checkout repository
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with:
ref: ${{ needs.get-artifacts.outputs.base || github.ref }}
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 - uses: actions/setup-python@v5
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
with: with:
cache-dependency-path: tests/requirements.txt cache-dependency-path: tests/requirements.txt
cache: "pip" cache: 'pip'
python-version: "3.x" python-version: '3.x'
- name: Install dependencies - name: Install dependencies
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
@ -266,17 +234,17 @@ jobs:
- name: Wokwi CI Server - name: Wokwi CI Server
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: wokwi/wokwi-ci-server-action@a6fabb5a49e080158c7a1d121ea5b789536a82c3 # v1 uses: wokwi/wokwi-ci-server-action@v1
- name: Get binaries - name: Get binaries
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 uses: actions/download-artifact@v4
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }} run-id: ${{ github.event.workflow_run.id }}
name: tests-bin-${{ matrix.chip }}-${{ matrix.type }} name: tests-bin-${{ matrix.chip }}-${{ matrix.type }}
path: | path: |
~/.arduino/tests/${{ matrix.chip }} ~/.arduino/tests
- name: Run Tests - name: Run Tests
if: ${{ steps.check-tests.outputs.enabled == 'true' }} if: ${{ steps.check-tests.outputs.enabled == 'true' }}
@ -286,7 +254,7 @@ jobs:
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 ${{ env.WOKWI_TIMEOUT }}
- name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as cache - name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as cache
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 uses: actions/cache/save@v4
if: steps.check-tests.outputs.enabled == 'true' && needs.get-artifacts.outputs.pr_num if: steps.check-tests.outputs.enabled == 'true' && needs.get-artifacts.outputs.pr_num
with: with:
key: tests-${{ env.id }}-results-wokwi key: tests-${{ env.id }}-results-wokwi
@ -295,7 +263,7 @@ jobs:
tests/**/result_*.json tests/**/result_*.json
- name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as artifacts - name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@v4
if: always() if: always()
with: with:
name: tests-results-wokwi-${{ matrix.chip }}-${{ matrix.type }} name: tests-results-wokwi-${{ matrix.chip }}-${{ matrix.type }}
@ -305,7 +273,7 @@ jobs:
tests/**/result_*.json tests/**/result_*.json
- name: Report conclusion - name: Report conclusion
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 uses: actions/github-script@v7
if: always() if: always()
with: with:
script: | script: |

View file

@ -1,38 +1,23 @@
name: Push components to https://components.espressif.com name: Push components to https://components.espressif.com
on: on:
workflow_dispatch:
inputs:
tag:
description: 'Version to push to the component registry'
required: true
git_ref:
description: 'Git ref with the source to push to the component registry'
required: true
workflow_run: workflow_run:
workflows: ["ESP32 Arduino Release"] workflows: ["ESP32 Arduino Release"]
types: types:
- completed - completed
permissions:
contents: read
jobs: jobs:
upload_components: upload_components:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Get the release tag - name: Get the release tag
env:
head_branch: ${{ inputs.tag || github.event.workflow_run.head_branch }}
run: | run: |
if [ "${{ github.event.workflow_run.conclusion }}" != "success" ] && [ "${{ github.event_name }}" == "workflow_run" ]; then if [ "${{ github.event.workflow_run.conclusion }}" != "success" ]; then
echo "Release workflow failed. Exiting..." echo "Release workflow failed. Exiting..."
exit 1 exit 1
fi fi
# Read and sanitize the branch/tag name branch=${{ github.event.workflow_run.head_branch }}
branch=$(echo "$head_branch" | tr -cd '[:alnum:]/_.-')
if [[ $branch == refs/tags/* ]]; then if [[ $branch == refs/tags/* ]]; then
tag="${branch#refs/tags/}" tag="${branch#refs/tags/}"
elif [[ $branch =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then elif [[ $branch =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
@ -45,13 +30,12 @@ jobs:
echo "Tag: $tag" echo "Tag: $tag"
echo "RELEASE_TAG=$tag" >> $GITHUB_ENV echo "RELEASE_TAG=$tag" >> $GITHUB_ENV
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
with: with:
ref: ${{ inputs.git_ref || env.RELEASE_TAG }}
submodules: "recursive" submodules: "recursive"
- name: Upload components to the component registry - name: Upload components to the component registry
uses: espressif/upload-components-ci-action@b78a19fa5424714997596d3ecffa634aef8ae20b # v1.0.5 uses: espressif/upload-components-ci-action@v1
with: with:
name: arduino-esp32 name: arduino-esp32
version: ${{ env.RELEASE_TAG }} version: ${{ env.RELEASE_TAG }}

View file

@ -1,25 +0,0 @@
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
# Place the default settings in `.gitlab/workflows/common.yml` instead
include:
- ".gitlab/workflows/common.yml"
- ".gitlab/workflows/sample.yml"

View file

@ -1,26 +0,0 @@
#####################
# Default Variables #
#####################
stages:
- pre_check
- build
- test
- result
variables:
ESP_IDF_VERSION: "5.5"
ESP_ARDUINO_VERSION: "3.3.0"
#############
# `default` #
#############
default:
retry:
max: 2
when:
# In case of a runner failure we could hop to another one, or a network error could go away.
- runner_system_failure
# Job execution timeout may be caused by a network issue.
- job_execution_timeout

View file

@ -1,6 +0,0 @@
hello-world:
stage: test
script:
- echo "Hello, World from GitLab CI!"
rules:
- if: $CI_PIPELINE_SOURCE == "push"

View file

@ -12,9 +12,8 @@ default_language_version:
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: "cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b" # v5.0.0 rev: "v4.5.0"
hooks: hooks:
# Generic checks
- id: check-case-conflict - id: check-case-conflict
- id: check-symlinks - id: check-symlinks
- id: debug-statements - id: debug-statements
@ -26,85 +25,46 @@ repos:
args: [--fix=lf] args: [--fix=lf]
- id: trailing-whitespace - id: trailing-whitespace
args: [--markdown-linebreak-ext=md] args: [--markdown-linebreak-ext=md]
- repo: https://github.com/codespell-project/codespell
# JSON formatting rev: "v2.3.0"
- id: pretty-format-json hooks:
stages: [manual] - id: codespell
args: [--autofix] exclude: ^.*\.(svd|SVD)$
types_or: [json] - repo: https://github.com/pre-commit/mirrors-clang-format
exclude: | rev: "v18.1.3"
(?x)(
diagram\..*\.json$|
package\.json$|
^package\/.*$
)
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: "f6446549e5e97ec9665b9b03e75b87b445857f9a" # v18.1.3
hooks: hooks:
# C/C++ formatting
- id: clang-format - id: clang-format
types_or: [c, c++] types_or: [c, c++]
exclude: ^.*\/build_opt\.h$ exclude: ^.*\/build_opt\.h$
- repo: https://github.com/psf/black-pre-commit-mirror - repo: https://github.com/psf/black-pre-commit-mirror
rev: "a4920527036bb9a3f3e6055d595849d67d0da066" # 25.1.0 rev: "22.10.0"
hooks: hooks:
# Python formatting
- id: black - id: black
types_or: [python] types_or: [python]
args: [--line-length=120] #From the arduino code style. Add as argument rather than creating a new config file. args: [--line-length=120] #From the arduino code style. Add as argument rather than creating a new config file.
- repo: https://github.com/PyCQA/flake8 - repo: https://github.com/PyCQA/flake8
rev: "16f5f28a384f0781bebb37a08aa45e65b9526c50" # 7.2.0 rev: "7.0.0"
hooks: hooks:
# Python linting
- id: flake8 - id: flake8
types_or: [python] types_or: [python]
additional_dependencies: additional_dependencies:
- flake8-bugbear - flake8-bugbear
- flake8-comprehensions - flake8-comprehensions
- flake8-simplify - flake8-simplify
- repo: https://github.com/pre-commit/mirrors-prettier - repo: https://github.com/pre-commit/mirrors-prettier
rev: "ffb6a759a979008c0e6dff86e39f4745a2d9eac4" # v3.1.0 rev: "v3.1.0"
hooks: hooks:
# YAML formatting
- id: prettier - id: prettier
types_or: [yaml] types_or: [yaml]
- repo: https://github.com/codespell-project/codespell
rev: "63c8f8312b7559622c0d82815639671ae42132ac" # v2.4.1
hooks:
# Spell checking
- id: codespell
exclude: ^.*\.(svd|SVD)$
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: "a23f6b85d0fdd5bb9d564e2579e678033debbdff" # v0.10.0.1
hooks:
# Bash linting
- id: shellcheck
types: [shell]
- repo: https://github.com/openstack/bashate
rev: "fbd7c2534c2701351c603ff700ddf08202430a31" # 2.1.1
hooks:
# Bash formatting
- id: bashate
types: [shell]
args: ["-i", "E006"] # Ignore E006: Line too long
- repo: https://github.com/errata-ai/vale - repo: https://github.com/errata-ai/vale
rev: "dc4c47923788a413fb5677de6e3370d514aecb78" # v3.11.2 rev: "v3.0.7"
hooks: hooks:
# Sync vale styles and lint markdown and reStructuredText
- id: vale - id: vale
name: vale-sync name: vale-sync
language_version: "1.23.2" language_version: "1.21.6"
pass_filenames: false pass_filenames: false
args: [sync] args: [sync]
types_or: [markdown, rst] types_or: [markdown, rst]
- id: vale - id: vale
language_version: "1.23.2" language_version: "1.21.6"
types_or: [markdown, rst] types_or: [markdown, rst]

View file

@ -1,11 +0,0 @@
# Shellcheck configuration file for ESP32 Arduino core
# Optional checks. https://github.com/koalaman/shellcheck/wiki/optional
enable=add-default-case,deprecate-which,avoid-nullary-conditions
# Enable search for external sources
external-sources=true
# Search folder for sourced files.
# Set to the folder where the original script is located.
source-path=SCRIPTDIR

View file

@ -5,8 +5,8 @@
# export ARDUINO_SKIP_IDF_VERSION_CHECK=1 # export ARDUINO_SKIP_IDF_VERSION_CHECK=1
# idf.py build # idf.py build
set(min_supported_idf_version "5.3.0") set(min_supported_idf_version "5.1.0")
set(max_supported_idf_version "5.5.99") set(max_supported_idf_version "5.1.99")
set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}") set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}")
if ("${idf_version}" AND NOT "$ENV{ARDUINO_SKIP_IDF_VERSION_CHECK}") if ("${idf_version}" AND NOT "$ENV{ARDUINO_SKIP_IDF_VERSION_CHECK}")
@ -25,7 +25,6 @@ endif()
set(CORE_SRCS set(CORE_SRCS
cores/esp32/base64.cpp cores/esp32/base64.cpp
cores/esp32/cbuf.cpp cores/esp32/cbuf.cpp
cores/esp32/ColorFormat.c
cores/esp32/chip-debug-report.cpp cores/esp32/chip-debug-report.cpp
cores/esp32/esp32-hal-adc.c cores/esp32/esp32-hal-adc.c
cores/esp32/esp32-hal-bt.c cores/esp32/esp32-hal-bt.c
@ -33,7 +32,6 @@ set(CORE_SRCS
cores/esp32/esp32-hal-dac.c cores/esp32/esp32-hal-dac.c
cores/esp32/esp32-hal-gpio.c cores/esp32/esp32-hal-gpio.c
cores/esp32/esp32-hal-i2c.c cores/esp32/esp32-hal-i2c.c
cores/esp32/esp32-hal-i2c-ng.c
cores/esp32/esp32-hal-i2c-slave.c cores/esp32/esp32-hal-i2c-slave.c
cores/esp32/esp32-hal-ledc.c cores/esp32/esp32-hal-ledc.c
cores/esp32/esp32-hal-matrix.c cores/esp32/esp32-hal-matrix.c
@ -47,11 +45,9 @@ set(CORE_SRCS
cores/esp32/esp32-hal-timer.c cores/esp32/esp32-hal-timer.c
cores/esp32/esp32-hal-tinyusb.c cores/esp32/esp32-hal-tinyusb.c
cores/esp32/esp32-hal-touch.c cores/esp32/esp32-hal-touch.c
cores/esp32/esp32-hal-touch-ng.c
cores/esp32/esp32-hal-uart.c cores/esp32/esp32-hal-uart.c
cores/esp32/esp32-hal-rmt.c cores/esp32/esp32-hal-rmt.c
cores/esp32/Esp.cpp cores/esp32/Esp.cpp
cores/esp32/freertos_stats.cpp
cores/esp32/FunctionalInterrupt.cpp cores/esp32/FunctionalInterrupt.cpp
cores/esp32/HardwareSerial.cpp cores/esp32/HardwareSerial.cpp
cores/esp32/HEXBuilder.cpp cores/esp32/HEXBuilder.cpp
@ -97,7 +93,6 @@ set(ARDUINO_ALL_LIBRARIES
HTTPUpdate HTTPUpdate
Insights Insights
LittleFS LittleFS
Matter
NetBIOS NetBIOS
Network Network
OpenThread OpenThread
@ -117,10 +112,10 @@ set(ARDUINO_ALL_LIBRARIES
WiFi WiFi
WiFiProv WiFiProv
Wire Wire
Zigbee
) )
set(ARDUINO_LIBRARY_ArduinoOTA_SRCS libraries/ArduinoOTA/src/ArduinoOTA.cpp) set(ARDUINO_LIBRARY_ArduinoOTA_SRCS libraries/ArduinoOTA/src/ArduinoOTA.cpp)
set(ARDUINO_LIBRARY_ArduinoOTA_REQUIRES esp_https_ota)
set(ARDUINO_LIBRARY_AsyncUDP_SRCS libraries/AsyncUDP/src/AsyncUDP.cpp) set(ARDUINO_LIBRARY_AsyncUDP_SRCS libraries/AsyncUDP/src/AsyncUDP.cpp)
@ -165,28 +160,9 @@ set(ARDUINO_LIBRARY_LittleFS_SRCS libraries/LittleFS/src/LittleFS.cpp)
set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp) set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp)
set(ARDUINO_LIBRARY_OpenThread_SRCS set(ARDUINO_LIBRARY_OpenThread_SRCS
libraries/OpenThread/src/OThread.cpp
libraries/OpenThread/src/OThreadCLI.cpp libraries/OpenThread/src/OThreadCLI.cpp
libraries/OpenThread/src/OThreadCLI_Util.cpp) libraries/OpenThread/src/OThreadCLI_Util.cpp)
set(ARDUINO_LIBRARY_Matter_SRCS
libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.cpp
libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp
libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp
libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp
libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp
libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp
libraries/Matter/src/MatterEndpoints/MatterFan.cpp
libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp
libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp
libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp
libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp
libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp
libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp
libraries/Matter/src/MatterEndpoints/MatterThermostat.cpp
libraries/Matter/src/Matter.cpp
libraries/Matter/src/MatterEndPoint.cpp)
set(ARDUINO_LIBRARY_PPP_SRCS set(ARDUINO_LIBRARY_PPP_SRCS
libraries/PPP/src/PPP.cpp libraries/PPP/src/PPP.cpp
libraries/PPP/src/ppp.c) libraries/PPP/src/ppp.c)
@ -227,16 +203,6 @@ set(ARDUINO_LIBRARY_USB_SRCS
libraries/USB/src/USBMIDI.cpp libraries/USB/src/USBMIDI.cpp
libraries/USB/src/USBHIDMouse.cpp libraries/USB/src/USBHIDMouse.cpp
libraries/USB/src/USBHIDKeyboard.cpp libraries/USB/src/USBHIDKeyboard.cpp
libraries/USB/src/keyboardLayout/KeyboardLayout_da_DK.cpp
libraries/USB/src/keyboardLayout/KeyboardLayout_de_DE.cpp
libraries/USB/src/keyboardLayout/KeyboardLayout_en_US.cpp
libraries/USB/src/keyboardLayout/KeyboardLayout_es_ES.cpp
libraries/USB/src/keyboardLayout/KeyboardLayout_fr_FR.cpp
libraries/USB/src/keyboardLayout/KeyboardLayout_hu_HU.cpp
libraries/USB/src/keyboardLayout/KeyboardLayout_it_IT.cpp
libraries/USB/src/keyboardLayout/KeyboardLayout_pt_BR.cpp
libraries/USB/src/keyboardLayout/KeyboardLayout_pt_PT.cpp
libraries/USB/src/keyboardLayout/KeyboardLayout_sv_SE.cpp
libraries/USB/src/USBHIDGamepad.cpp libraries/USB/src/USBHIDGamepad.cpp
libraries/USB/src/USBHIDConsumerControl.cpp libraries/USB/src/USBHIDConsumerControl.cpp
libraries/USB/src/USBHIDSystemControl.cpp libraries/USB/src/USBHIDSystemControl.cpp
@ -246,11 +212,7 @@ set(ARDUINO_LIBRARY_USB_SRCS
set(ARDUINO_LIBRARY_WebServer_SRCS set(ARDUINO_LIBRARY_WebServer_SRCS
libraries/WebServer/src/WebServer.cpp libraries/WebServer/src/WebServer.cpp
libraries/WebServer/src/Parsing.cpp libraries/WebServer/src/Parsing.cpp
libraries/WebServer/src/detail/mimetable.cpp libraries/WebServer/src/detail/mimetable.cpp)
libraries/WebServer/src/middleware/MiddlewareChain.cpp
libraries/WebServer/src/middleware/AuthenticationMiddleware.cpp
libraries/WebServer/src/middleware/CorsMiddleware.cpp
libraries/WebServer/src/middleware/LoggingMiddleware.cpp)
set(ARDUINO_LIBRARY_NetworkClientSecure_SRCS set(ARDUINO_LIBRARY_NetworkClientSecure_SRCS
libraries/NetworkClientSecure/src/ssl_client.cpp libraries/NetworkClientSecure/src/ssl_client.cpp
@ -278,37 +240,6 @@ set(ARDUINO_LIBRARY_WiFiProv_SRCS libraries/WiFiProv/src/WiFiProv.cpp)
set(ARDUINO_LIBRARY_Wire_SRCS libraries/Wire/src/Wire.cpp) set(ARDUINO_LIBRARY_Wire_SRCS libraries/Wire/src/Wire.cpp)
set(ARDUINO_LIBRARY_Zigbee_SRCS
libraries/Zigbee/src/ZigbeeCore.cpp
libraries/Zigbee/src/ZigbeeEP.cpp
libraries/Zigbee/src/ZigbeeHandlers.cpp
libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp
libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp
libraries/Zigbee/src/ep/ZigbeeDimmableLight.cpp
libraries/Zigbee/src/ep/ZigbeeLight.cpp
libraries/Zigbee/src/ep/ZigbeeSwitch.cpp
libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp
libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
libraries/Zigbee/src/ep/ZigbeeFlowSensor.cpp
libraries/Zigbee/src/ep/ZigbeePressureSensor.cpp
libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp
libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp
libraries/Zigbee/src/ep/ZigbeeContactSwitch.cpp
libraries/Zigbee/src/ep/ZigbeeDoorWindowHandle.cpp
libraries/Zigbee/src/ep/ZigbeeWindowCovering.cpp
libraries/Zigbee/src/ep/ZigbeeVibrationSensor.cpp
libraries/Zigbee/src/ep/ZigbeeAnalog.cpp
libraries/Zigbee/src/ep/ZigbeeRangeExtender.cpp
libraries/Zigbee/src/ep/ZigbeeGateway.cpp
libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.cpp
libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.cpp
libraries/Zigbee/src/ep/ZigbeePM25Sensor.cpp
libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp
libraries/Zigbee/src/ep/ZigbeeBinary.cpp
libraries/Zigbee/src/ep/ZigbeePowerOutlet.cpp
libraries/Zigbee/src/ep/ZigbeeFanControl.cpp
)
set(ARDUINO_LIBRARY_BLE_SRCS set(ARDUINO_LIBRARY_BLE_SRCS
libraries/BLE/src/BLE2901.cpp libraries/BLE/src/BLE2901.cpp
libraries/BLE/src/BLE2902.cpp libraries/BLE/src/BLE2902.cpp
@ -362,21 +293,17 @@ endforeach()
set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ ${ARDUINO_LIBRARIES_INCLUDEDIRS}) set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ ${ARDUINO_LIBRARIES_INCLUDEDIRS})
set(srcs ${CORE_SRCS} ${ARDUINO_LIBRARIES_SRCS}) set(srcs ${CORE_SRCS} ${ARDUINO_LIBRARIES_SRCS})
set(priv_includes cores/esp32/libb64) set(priv_includes cores/esp32/libb64)
set(requires spi_flash esp_partition mbedtls wpa_supplicant esp_adc esp_eth http_parser esp_ringbuf esp_driver_gptimer esp_driver_usb_serial_jtag driver esp_http_client esp_https_ota) set(requires spi_flash esp_partition mbedtls wpa_supplicant esp_adc esp_eth http_parser espressif__network_provisioning)
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid usb esp_psram ${ARDUINO_LIBRARIES_REQUIRES}) set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid usb esp_psram ${ARDUINO_LIBRARIES_REQUIRES})
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThread) if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThread)
#if(CONFIG_SOC_IEEE802154_SUPPORTED) # Does not work! #if(CONFIG_SOC_IEEE802154_SUPPORTED) # Does not work!
#if(CONFIG_OPENTHREAD_ENABLED) # Does not work! #if(CONFIG_OPENTHREAD_ENABLED) # Does not work!
if(IDF_TARGET STREQUAL "esp32c6" OR IDF_TARGET STREQUAL "esp32h2" OR IDF_TARGET STREQUAL "esp32c5") # Sadly only this works if(IDF_TARGET STREQUAL "esp32c6" OR IDF_TARGET STREQUAL "esp32h2") # Sadly only this works
list(APPEND requires openthread) list(APPEND requires openthread)
endif() endif()
endif() endif()
if(IDF_TARGET STREQUAL "esp32p4")
list(APPEND requires esp_driver_touch_sens)
endif()
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires}) idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
if(NOT CONFIG_FREERTOS_HZ EQUAL 1000 AND NOT "$ENV{ARDUINO_SKIP_TICK_CHECK}") if(NOT CONFIG_FREERTOS_HZ EQUAL 1000 AND NOT "$ENV{ARDUINO_SKIP_TICK_CHECK}")
@ -416,21 +343,9 @@ function(maybe_add_component component_name)
endif() endif()
endfunction() endfunction()
if(IDF_TARGET MATCHES "esp32s2|esp32s3|esp32p4" AND CONFIG_TINYUSB_ENABLED) if(IDF_TARGET MATCHES "esp32s2|esp32s3" AND CONFIG_TINYUSB_ENABLED)
maybe_add_component(arduino_tinyusb) maybe_add_component(arduino_tinyusb)
endif() endif()
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA) if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA)
maybe_add_component(esp_https_ota) maybe_add_component(esp_https_ota)
endif() endif()
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ESP_SR)
maybe_add_component(espressif__esp_sr)
endif()
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_Matter)
maybe_add_component(espressif__esp_matter)
endif()
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_LittleFS)
maybe_add_component(joltwallet__littlefs)
endif()
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_WiFiProv)
maybe_add_component(espressif__network_provisioning)
endif()

View file

@ -266,11 +266,6 @@ config ARDUINO_SELECTIVE_Wire
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
default y default y
config ARDUINO_SELECTIVE_ESP_SR
bool "Enable ESP-SR"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_EEPROM config ARDUINO_SELECTIVE_EEPROM
bool "Enable EEPROM" bool "Enable EEPROM"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
@ -291,11 +286,6 @@ config ARDUINO_SELECTIVE_Update
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
default y default y
config ARDUINO_SELECTIVE_Zigbee
bool "Enable Zigbee"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_FS config ARDUINO_SELECTIVE_FS
bool "Enable FS" bool "Enable FS"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
@ -368,11 +358,6 @@ config ARDUINO_SELECTIVE_HTTPClient
select ARDUINO_SELECTIVE_NetworkClientSecure select ARDUINO_SELECTIVE_NetworkClientSecure
default y default y
config ARDUINO_SELECTIVE_Matter
bool "Enable Matter"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
default y
config ARDUINO_SELECTIVE_NetBIOS config ARDUINO_SELECTIVE_NetBIOS
bool "Enable NetBIOS" bool "Enable NetBIOS"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
@ -414,19 +399,4 @@ config ARDUINO_SELECTIVE_SimpleBLE
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
default y default y
config ARDUINO_SELECTIVE_RainMaker
bool "Enable RainMaker"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_OpenThread
bool "Enable OpenThread"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_Insights
bool "Enable Insights"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
endmenu endmenu

View file

@ -1,13 +1,8 @@
# Arduino core for the ESP32, ESP32-C3, ESP32-C6, ESP32-H2, ESP32-P4, ESP32-S2 and ESP32-S3. # Arduino core for the ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 and ESP32-H2
[![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) [![Build Status](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml/badge.svg?branch=master&event=push)](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml) [![External Libraries Test](https://github.com/espressif/arduino-esp32/actions/workflows/lib.yml/badge.svg?branch=master&event=schedule)](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md) [![Hardware Tests](https://github.com/espressif/arduino-esp32/blob/gh-pages/runtime-tests-results/badge.svg)](https://github.com/espressif/arduino-esp32/actions/workflows/tests_results.yml)
[![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)
[![External Libraries Test](https://img.shields.io/github/actions/workflow/status/espressif/arduino-esp32/lib.yml?branch=master&event=schedule&label=External%20Libraries%20Test)](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md)
[![Runtime Tests](https://github.com/espressif/arduino-esp32/blob/gh-pages/runtime-tests-results/badge.svg)](https://github.com/espressif/arduino-esp32/blob/gh-pages/runtime-tests-results/RUNTIME_TESTS_REPORT.md)
### Need help or have a question? Join the chat at [Discord](https://discord.gg/8xY6e9crwv) or [open a new Discussion](https://github.com/espressif/arduino-esp32/discussions) ### Need help or have a question? Join the chat at [Gitter](https://gitter.im/espressif/arduino-esp32) or [open a new Discussion](https://github.com/espressif/arduino-esp32/discussions)
[![Discord invite](https://img.shields.io/discord/1327272229427216425?logo=discord&logoColor=white&logoSize=auto&label=Discord)](https://discord.gg/8xY6e9crwv)
## Contents ## Contents
@ -21,17 +16,9 @@
### Development Status ### Development Status
#### Latest Stable Release Latest Stable Release [![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/)
[![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/latest/) Latest Development Release [![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) [![Release Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) [![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/)
[![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/latest/)
[![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg)](https://github.com/espressif/arduino-esp32/releases/latest/)
#### Latest Development Release
[![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg)](https://github.com/espressif/arduino-esp32/releases/)
[![Release Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/)
[![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg)](https://github.com/espressif/arduino-esp32/releases/)
### Development Planning ### Development Planning
@ -67,17 +54,15 @@ Here are the ESP32 series supported by the Arduino-ESP32 project:
| **SoC** | **Stable** | **Development** | **Datasheet** | | **SoC** | **Stable** | **Development** | **Datasheet** |
|----------|:----------:|:---------------:|:-------------------------------------------------------------------------------------------------:| |----------|:----------:|:---------------:|:-------------------------------------------------------------------------------------------------:|
| ESP32 | Yes | Yes | [ESP32](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) | | ESP32 | Yes | Yes | [ESP32](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) |
| ESP32-S2 | Yes | Yes | [ESP32-S2](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) |
| ESP32-C3 | Yes | Yes | [ESP32-C3](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) | | ESP32-C3 | Yes | Yes | [ESP32-C3](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) |
| ESP32-S3 | Yes | Yes | [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) |
| ESP32-C6 | Yes | Yes | [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_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-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) |
| ESP32-S2 | Yes | Yes | [ESP32-S2](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) |
| ESP32-S3 | Yes | Yes | [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) |
> [!NOTE] > [!NOTE]
> ESP32-C2 is also supported by Arduino-ESP32 but requires using Arduino as an ESP-IDF component or rebuilding the static libraries. > ESP32-C2 is also supported by Arduino-ESP32 but requires rebuilding the static libraries. This is not trivial and requires a good understanding of the ESP-IDF
> For more information, see the [Arduino as an ESP-IDF component documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/esp-idf_component.html) or the > build system. For more information, see the [Lib Builder documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/lib_builder.html).
> [Lib Builder documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/lib_builder.html), respectively.
For more details visit the [supported chips](https://docs.espressif.com/projects/arduino-esp32/en/latest/getting_started.html#supported-soc-s) documentation page. For more details visit the [supported chips](https://docs.espressif.com/projects/arduino-esp32/en/latest/getting_started.html#supported-soc-s) documentation page.

11273
boards.txt

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,7 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "esp32-hal.h"
#include "esp8266-compat.h" #include "esp8266-compat.h"
#include "soc/gpio_reg.h" #include "soc/gpio_reg.h"
@ -40,9 +41,6 @@
#include "binary.h" #include "binary.h"
#include "extra_attr.h" #include "extra_attr.h"
#include "pins_arduino.h"
#include "esp32-hal.h"
#define PI 3.1415926535897932384626433832795 #define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398 #define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559 #define TWO_PI 6.283185307179586476925286766559
@ -144,7 +142,7 @@
#endif #endif
#define EXTERNAL_NUM_INTERRUPTS NUM_DIGITAL_PINS // All GPIOs #define EXTERNAL_NUM_INTERRUPTS NUM_DIGITAL_PINS // All GPIOs
#define analogInputToDigitalPin(p) (((p) < NUM_ANALOG_INPUTS) ? (analogChannelToDigitalPin(p)) : -1) #define analogInputToDigitalPin(p) (((p) < NUM_ANALOG_INPUTS) ? (analogChannelToDigitalPin(p)) : -1)
#define digitalPinToInterrupt(p) ((((uint8_t)digitalPinToGPIONumber(p)) < NUM_DIGITAL_PINS) ? (p) : NOT_AN_INTERRUPT) #define digitalPinToInterrupt(p) ((((uint8_t)digitalPinToGPIONumber(p)) < NUM_DIGITAL_PINS) ? digitalPinToGPIONumber(p) : NOT_AN_INTERRUPT)
#define digitalPinHasPWM(p) (((uint8_t)digitalPinToGPIONumber(p)) < NUM_DIGITAL_PINS) #define digitalPinHasPWM(p) (((uint8_t)digitalPinToGPIONumber(p)) < NUM_DIGITAL_PINS)
typedef bool boolean; typedef bool boolean;
@ -201,7 +199,6 @@ void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
#include "Udp.h" #include "Udp.h"
#include "HardwareSerial.h" #include "HardwareSerial.h"
#include "Esp.h" #include "Esp.h"
#include "freertos_stats.h"
// Use float-compatible stl abs() and round(), we don't use Arduino macros to avoid issues with the C++ libraries // Use float-compatible stl abs() and round(), we don't use Arduino macros to avoid issues with the C++ libraries
using std::abs; using std::abs;
@ -251,7 +248,7 @@ void noTone(uint8_t _pin);
#endif /* __cplusplus */ #endif /* __cplusplus */
// must be applied last as it overrides some of the above #include "pins_arduino.h"
#include "io_pin_remap.h" #include "io_pin_remap.h"
#endif /* _ESP32_CORE_ARDUINO_H_ */ #endif /* _ESP32_CORE_ARDUINO_H_ */

View file

@ -1,281 +0,0 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ColorFormat.h"
#include <math.h>
// define a clamp macro to substitute the std::clamp macro which is available from C++17 onwards
#define clamp(a, min, max) ((a) < (min) ? (min) : ((a) > (max) ? (max) : (a)))
const espHsvColor_t HSV_BLACK = {0, 0, 0};
const espHsvColor_t HSV_WHITE = {0, 0, 254};
const espHsvColor_t HSV_RED = {0, 254, 254};
const espHsvColor_t HSV_YELLOW = {42, 254, 254};
const espHsvColor_t HSV_GREEN = {84, 254, 254};
const espHsvColor_t HSV_CYAN = {127, 254, 254};
const espHsvColor_t HSV_BLUE = {169, 254, 254};
const espHsvColor_t HSV_MAGENTA = {211, 254, 254};
const espRgbColor_t RGB_BLACK = {0, 0, 0};
const espRgbColor_t RGB_WHITE = {255, 255, 255};
const espRgbColor_t RGB_RED = {255, 0, 0};
const espRgbColor_t RGB_YELLOW = {255, 255, 0};
const espRgbColor_t RGB_GREEN = {0, 255, 0};
const espRgbColor_t RGB_CYAN = {0, 255, 255};
const espRgbColor_t RGB_BLUE = {0, 0, 255};
const espRgbColor_t RGB_MAGENTA = {255, 0, 255};
// main color temperature values
const espCtColor_t COOL_WHITE_COLOR_TEMPERATURE = {142};
const espCtColor_t DAYLIGHT_WHITE_COLOR_TEMPERATURE = {181};
const espCtColor_t WHITE_COLOR_TEMPERATURE = {250};
const espCtColor_t SOFT_WHITE_COLOR_TEMPERATURE = {370};
const espCtColor_t WARM_WHITE_COLOR_TEMPERATURE = {454};
espRgbColor_t espHsvToRgbColor(uint16_t h, uint8_t s, uint8_t v) {
espHsvColor_t hsv = {h, s, v};
return espHsvColorToRgbColor(hsv);
}
espRgbColor_t espHsvColorToRgbColor(espHsvColor_t hsv) {
espRgbColor_t rgb;
uint8_t region, p, q, t;
uint32_t h, s, v, remainder;
if (hsv.s == 0) {
rgb.r = rgb.g = rgb.b = hsv.v;
} else {
h = hsv.h;
s = hsv.s;
v = hsv.v;
region = h / 43;
remainder = (h - (region * 43)) * 6;
p = (v * (255 - s)) >> 8;
q = (v * (255 - ((s * remainder) >> 8))) >> 8;
t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
switch (region) {
case 0: rgb.r = v, rgb.g = t, rgb.b = p; break;
case 1: rgb.r = q, rgb.g = v, rgb.b = p; break;
case 2: rgb.r = p, rgb.g = v, rgb.b = t; break;
case 3: rgb.r = p, rgb.g = q, rgb.b = v; break;
case 4: rgb.r = t, rgb.g = p, rgb.b = v; break;
case 5:
default: rgb.r = v, rgb.g = p, rgb.b = q; break;
}
}
return rgb;
}
espHsvColor_t espRgbToHsvColor(uint8_t r, uint8_t g, uint8_t b) {
espRgbColor_t rgb = {r, g, b};
return espRgbColorToHsvColor(rgb);
}
espHsvColor_t espRgbColorToHsvColor(espRgbColor_t rgb) {
espHsvColor_t hsv;
uint8_t rgbMin, rgbMax;
rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);
hsv.v = rgbMax;
if (hsv.v == 0) {
hsv.h = 0;
hsv.s = 0;
return hsv;
}
hsv.s = 255 * (rgbMax - rgbMin) / hsv.v;
if (hsv.s == 0) {
hsv.h = 0;
return hsv;
}
if (rgbMax == rgb.r) {
hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);
} else if (rgbMax == rgb.g) {
hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);
} else {
hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);
}
return hsv;
}
espRgbColor_t espXYColorToRgbColor(uint8_t Level, espXyColor_t xy) {
return espXYToRgbColor(Level, xy.x, xy.y, true);
}
espRgbColor_t espXYToRgbColor(uint8_t Level, uint16_t current_X, uint16_t current_Y, bool addXYZScaling) {
// convert xyY color space to RGB
// https://www.easyrgb.com/en/math.php
// https://en.wikipedia.org/wiki/SRGB
// refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
// The current_X/current_Y attribute contains the current value of the normalized chromaticity value of x/y.
// The value of x/y shall be related to the current_X/current_Y attribute by the relationship
// x = current_X/65536
// y = current_Y/65536
// z = 1-x-y
espRgbColor_t rgb;
float x, y, z;
float X, Y, Z;
float r, g, b;
x = ((float)current_X) / 65535.0f;
y = ((float)current_Y) / 65535.0f;
z = 1.0f - x - y;
// Calculate XYZ values
// Y - given brightness in 0 - 1 range
Y = ((float)Level) / 254.0f;
X = (Y / y) * x;
Z = (Y / y) * z;
// X, Y and Z input refer to a D65/2° standard illuminant.
// sR, sG and sB (standard RGB) output range = 0 ÷ 255
// convert XYZ to RGB - CIE XYZ to sRGB
if (addXYZScaling) {
X = X / 100.0f;
Y = Y / 100.0f;
Z = Z / 100.0f;
}
r = (X * 3.2406f) - (Y * 1.5372f) - (Z * 0.4986f);
g = -(X * 0.9689f) + (Y * 1.8758f) + (Z * 0.0415f);
b = (X * 0.0557f) - (Y * 0.2040f) + (Z * 1.0570f);
// apply gamma 2.2 correction
r = (r <= 0.0031308f ? 12.92f * r : (1.055f) * pow(r, (1.0f / 2.4f)) - 0.055f);
g = (g <= 0.0031308f ? 12.92f * g : (1.055f) * pow(g, (1.0f / 2.4f)) - 0.055f);
b = (b <= 0.0031308f ? 12.92f * b : (1.055f) * pow(b, (1.0f / 2.4f)) - 0.055f);
// Round off
r = clamp(r, 0, 1);
g = clamp(g, 0, 1);
b = clamp(b, 0, 1);
// these rgb values are in the range of 0 to 1, convert to limit of HW specific LED
rgb.r = (uint8_t)(r * 255);
rgb.g = (uint8_t)(g * 255);
rgb.b = (uint8_t)(b * 255);
return rgb;
}
espXyColor_t espRgbToXYColor(uint8_t r, uint8_t g, uint8_t b) {
espRgbColor_t rgb = {r, g, b};
return espRgbColorToXYColor(rgb);
}
espXyColor_t espRgbColorToXYColor(espRgbColor_t rgb) {
// convert RGB to xy color space
// https://www.easyrgb.com/en/math.php
// https://en.wikipedia.org/wiki/SRGB
// refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
espXyColor_t xy;
float r, g, b;
float X, Y, Z;
float x, y;
r = ((float)rgb.r) / 255.0f;
g = ((float)rgb.g) / 255.0f;
b = ((float)rgb.b) / 255.0f;
// convert RGB to XYZ - sRGB to CIE XYZ
r = (r <= 0.04045f ? r / 12.92f : pow((r + 0.055f) / 1.055f, 2.4f));
g = (g <= 0.04045f ? g / 12.92f : pow((g + 0.055f) / 1.055f, 2.4f));
b = (b <= 0.04045f ? b / 12.92f : pow((b + 0.055f) / 1.055f, 2.4f));
// https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
X = r * 0.649926f + g * 0.103455f + b * 0.197109f;
Y = r * 0.234327f + g * 0.743075f + b * 0.022598f;
Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f;
// sR, sG and sB (standard RGB) input range = 0 ÷ 255
// X, Y and Z output refer to a D65/2° standard illuminant.
X = r * 0.4124564f + g * 0.3575761f + b * 0.1804375f;
Y = r * 0.2126729f + g * 0.7151522f + b * 0.0721750f;
Z = r * 0.0193339f + g * 0.1191920f + b * 0.9503041f;
// Calculate xy values
x = X / (X + Y + Z);
y = Y / (X + Y + Z);
// convert to 0-65535 range
xy.x = (uint16_t)(x * 65535);
xy.y = (uint16_t)(y * 65535);
return xy;
}
espRgbColor_t espCTToRgbColor(uint16_t ct) {
espCtColor_t ctColor = {ct};
return espCTColorToRgbColor(ctColor);
}
espRgbColor_t espCTColorToRgbColor(espCtColor_t ct) {
espRgbColor_t rgb = {0, 0, 0};
float r, g, b;
if (ct.ctMireds == 0) {
return rgb;
}
// Algorithm credits to Tanner Helland: https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
// Convert Mireds to centiKelvins. k = 1,000,000/mired
float ctCentiKelvin = 10000 / ct.ctMireds;
// Red
if (ctCentiKelvin <= 66) {
r = 255;
} else {
r = 329.698727446f * pow(ctCentiKelvin - 60, -0.1332047592f);
}
// Green
if (ctCentiKelvin <= 66) {
g = 99.4708025861f * log(ctCentiKelvin) - 161.1195681661f;
} else {
g = 288.1221695283f * pow(ctCentiKelvin - 60, -0.0755148492f);
}
// Blue
if (ctCentiKelvin >= 66) {
b = 255;
} else {
if (ctCentiKelvin <= 19) {
b = 0;
} else {
b = 138.5177312231 * log(ctCentiKelvin - 10) - 305.0447927307;
}
}
rgb.r = (uint8_t)clamp(r, 0, 255);
rgb.g = (uint8_t)clamp(g, 0, 255);
rgb.b = (uint8_t)clamp(b, 0, 255);
return rgb;
}

View file

@ -1,71 +0,0 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
struct RgbColor_t {
uint8_t r;
uint8_t g;
uint8_t b;
};
struct HsvColor_t {
uint16_t h;
uint8_t s;
uint8_t v;
};
struct XyColor_t {
uint16_t x;
uint16_t y;
};
struct CtColor_t {
uint16_t ctMireds;
};
typedef struct RgbColor_t espRgbColor_t;
typedef struct HsvColor_t espHsvColor_t;
typedef struct XyColor_t espXyColor_t;
typedef struct CtColor_t espCtColor_t;
espRgbColor_t espXYToRgbColor(uint8_t Level, uint16_t current_X, uint16_t current_Y, bool addXYZScaling);
espRgbColor_t espXYColorToRgb(uint8_t Level, espXyColor_t xy);
espXyColor_t espRgbColorToXYColor(espRgbColor_t rgb);
espXyColor_t espRgbToXYColor(uint8_t r, uint8_t g, uint8_t b);
espRgbColor_t espHsvColorToRgbColor(espHsvColor_t hsv);
espRgbColor_t espHsvToRgbColor(uint16_t h, uint8_t s, uint8_t v);
espRgbColor_t espCTColorToRgbColor(espCtColor_t ct);
espRgbColor_t espCTToRgbColor(uint16_t ct);
espHsvColor_t espRgbColorToHsvColor(espRgbColor_t rgb);
espHsvColor_t espRgbToHsvColor(uint8_t r, uint8_t g, uint8_t b);
extern const espHsvColor_t HSV_BLACK, HSV_WHITE, HSV_RED, HSV_YELLOW, HSV_GREEN, HSV_CYAN, HSV_BLUE, HSV_MAGENTA;
extern const espCtColor_t COOL_WHITE_COLOR_TEMPERATURE, DAYLIGHT_WHITE_COLOR_TEMPERATURE, WHITE_COLOR_TEMPERATURE, SOFT_WHITE_COLOR_TEMPERATURE,
WARM_WHITE_COLOR_TEMPERATURE;
extern const espRgbColor_t RGB_BLACK, RGB_WHITE, RGB_RED, RGB_YELLOW, RGB_GREEN, RGB_CYAN, RGB_BLUE, RGB_MAGENTA;
#ifdef __cplusplus
}
#endif

View file

@ -21,7 +21,6 @@
#include "Esp.h" #include "Esp.h"
#include "esp_sleep.h" #include "esp_sleep.h"
#include "spi_flash_mmap.h" #include "spi_flash_mmap.h"
#include "esp_idf_version.h"
#include <memory> #include <memory>
#include <soc/soc.h> #include <soc/soc.h>
#include <esp_partition.h> #include <esp_partition.h>
@ -61,12 +60,6 @@ extern "C" {
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/spi_flash.h" #include "esp32h2/rom/spi_flash.h"
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32h2 is located at 0x0000 #define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32h2 is located at 0x0000
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/spi_flash.h"
#define ESP_FLASH_IMAGE_BASE 0x2000 // Esp32p4 is located at 0x2000
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/spi_flash.h"
#define ESP_FLASH_IMAGE_BASE 0x2000 // Esp32c5 is located at 0x2000
#else #else
#error Target CONFIG_IDF_TARGET is not supported #error Target CONFIG_IDF_TARGET is not supported
#endif #endif
@ -281,7 +274,7 @@ const char *EspClass::getChipModel(void) {
return "ESP32-D0WD"; return "ESP32-D0WD";
} }
case EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5: return "ESP32-D2WD"; case EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5: return "ESP32-D2WD";
case EFUSE_RD_CHIP_VER_PKG_ESP32U4WDH: return "ESP32-U4WDH"; case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2: return "ESP32-PICO-D2";
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4: return "ESP32-PICO-D4"; case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4: return "ESP32-PICO-D4";
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302: return "ESP32-PICO-V3-02"; case EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302: return "ESP32-PICO-V3-02";
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDR2V3: return "ESP32-D0WDR2-V3"; case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDR2V3: return "ESP32-D0WDR2-V3";
@ -304,13 +297,7 @@ const char *EspClass::getChipModel(void) {
case CHIP_ESP32C2: return "ESP32-C2"; case CHIP_ESP32C2: return "ESP32-C2";
case CHIP_ESP32C6: return "ESP32-C6"; case CHIP_ESP32C6: return "ESP32-C6";
case CHIP_ESP32H2: return "ESP32-H2"; case CHIP_ESP32H2: return "ESP32-H2";
case CHIP_ESP32P4: return "ESP32-P4"; default: return "UNKNOWN";
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
case CHIP_ESP32C5: return "ESP32-C5";
case CHIP_ESP32C61: return "ESP32-C61";
case CHIP_ESP32H21: return "ESP32-H21";
#endif
default: return "UNKNOWN";
} }
#endif #endif
} }
@ -348,8 +335,6 @@ uint32_t EspClass::getFlashChipSpeed(void) {
return magicFlashChipSpeed(fhdr.spi_speed); return magicFlashChipSpeed(fhdr.spi_speed);
} }
// FIXME for P4
#if !defined(CONFIG_IDF_TARGET_ESP32P4)
FlashMode_t EspClass::getFlashChipMode(void) { FlashMode_t EspClass::getFlashChipMode(void) {
#if CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32S2
uint32_t spi_ctrl = REG_READ(PERIPHS_SPI_FLASH_CTRL); uint32_t spi_ctrl = REG_READ(PERIPHS_SPI_FLASH_CTRL);
@ -376,7 +361,6 @@ FlashMode_t EspClass::getFlashChipMode(void) {
} }
return (FM_DOUT); return (FM_DOUT);
} }
#endif // if !defined(CONFIG_IDF_TARGET_ESP32P4)
uint32_t EspClass::magicFlashChipSize(uint8_t byte) { uint32_t EspClass::magicFlashChipSize(uint8_t byte) {
/* /*

View file

@ -19,8 +19,8 @@
#include "esp_partition.h" #include "esp_partition.h"
#include "esp_ota_ops.h" #include "esp_ota_ops.h"
#include "esp_image_format.h" #include "esp_image_format.h"
#include "pins_arduino.h"
#include "esp32-hal.h" #include "esp32-hal.h"
#include "pins_arduino.h"
#include "firmware_msc_fat.h" #include "firmware_msc_fat.h"
#include "spi_flash_mmap.h" #include "spi_flash_mmap.h"

View file

@ -286,14 +286,14 @@ bool HWCDC::deinit(void *busptr) {
running = true; running = true;
// Setting USB D+ D- pins // Setting USB D+ D- pins
bool retCode = true; bool retCode = true;
retCode &= perimanClearPinBus(USB_INT_PHY0_DM_GPIO_NUM); retCode &= perimanClearPinBus(USB_DM_GPIO_NUM);
retCode &= perimanClearPinBus(USB_INT_PHY0_DP_GPIO_NUM); retCode &= perimanClearPinBus(USB_DP_GPIO_NUM);
if (retCode) { if (retCode) {
// Force the host to re-enumerate (BUS_RESET) // Force the host to re-enumerate (BUS_RESET)
pinMode(USB_INT_PHY0_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN); pinMode(USB_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN);
pinMode(USB_INT_PHY0_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN); pinMode(USB_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN);
digitalWrite(USB_INT_PHY0_DM_GPIO_NUM, LOW); digitalWrite(USB_DM_GPIO_NUM, LOW);
digitalWrite(USB_INT_PHY0_DP_GPIO_NUM, LOW); digitalWrite(USB_DP_GPIO_NUM, LOW);
} }
// release the flag // release the flag
running = false; running = false;
@ -323,11 +323,11 @@ void HWCDC::begin(unsigned long baud) {
// delay(10); // USB Host has to enumerate it again // delay(10); // USB Host has to enumerate it again
// Peripheral Manager setting for USB D+ D- pins // Peripheral Manager setting for USB D+ D- pins
uint8_t pin = USB_INT_PHY0_DM_GPIO_NUM; uint8_t pin = USB_DM_GPIO_NUM;
if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DM, (void *)this, -1, -1)) { if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DM, (void *)this, -1, -1)) {
goto err; goto err;
} }
pin = USB_INT_PHY0_DP_GPIO_NUM; pin = USB_DP_GPIO_NUM;
if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DP, (void *)this, -1, -1)) { if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DP, (void *)this, -1, -1)) {
goto err; goto err;
} }
@ -603,7 +603,6 @@ void HWCDC::setDebugOutput(bool en) {
} else { } else {
ets_install_putc2(NULL); ets_install_putc2(NULL);
} }
ets_install_putc1(NULL); // closes UART log output
} }
#if ARDUINO_USB_MODE && ARDUINO_USB_CDC_ON_BOOT // Hardware JTAG CDC selected #if ARDUINO_USB_MODE && ARDUINO_USB_CDC_ON_BOOT // Hardware JTAG CDC selected

View file

@ -20,7 +20,6 @@
#include <inttypes.h> #include <inttypes.h>
#include "Stream.h" #include "Stream.h"
#include <functional>
class HardwareI2C : public Stream { class HardwareI2C : public Stream {
public: public:
@ -37,7 +36,6 @@ public:
virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0; virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0;
virtual size_t requestFrom(uint8_t address, size_t len) = 0; virtual size_t requestFrom(uint8_t address, size_t len) = 0;
// Update base class to use std::function virtual void onReceive(void (*)(int)) = 0;
virtual void onReceive(const std::function<void(int)> &) = 0; virtual void onRequest(void (*)(void)) = 0;
virtual void onRequest(const std::function<void()> &) = 0;
}; };

View file

@ -11,34 +11,31 @@
#include "driver/uart.h" #include "driver/uart.h"
#include "freertos/queue.h" #include "freertos/queue.h"
#if (SOC_UART_LP_NUM >= 1) #ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
#define UART_HW_FIFO_LEN(uart_num) ((uart_num < SOC_UART_HP_NUM) ? SOC_UART_FIFO_LEN : SOC_LP_UART_FIFO_LEN) #define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048
#else #endif
#define UART_HW_FIFO_LEN(uart_num) SOC_UART_FIFO_LEN
#ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES - 1)
#endif
#ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1
#endif #endif
void serialEvent(void) __attribute__((weak)); void serialEvent(void) __attribute__((weak));
void serialEvent(void) {}
#if SOC_UART_NUM > 1 #if SOC_UART_NUM > 1
void serialEvent1(void) __attribute__((weak)); void serialEvent1(void) __attribute__((weak));
void serialEvent1(void) {}
#endif /* SOC_UART_NUM > 1 */ #endif /* SOC_UART_NUM > 1 */
#if SOC_UART_NUM > 2 #if SOC_UART_NUM > 2
void serialEvent2(void) __attribute__((weak)); void serialEvent2(void) __attribute__((weak));
void serialEvent2(void) {}
#endif /* SOC_UART_NUM > 2 */ #endif /* SOC_UART_NUM > 2 */
#if SOC_UART_NUM > 3
void serialEvent3(void) __attribute__((weak));
#endif /* SOC_UART_NUM > 3 */
#if SOC_UART_NUM > 4
void serialEvent4(void) __attribute__((weak));
#endif /* SOC_UART_NUM > 4 */
#if SOC_UART_NUM > 5
void serialEvent5(void) __attribute__((weak));
#endif /* SOC_UART_NUM > 5 */
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
// There is always Seria0 for UART0 // There is always Seria0 for UART0
HardwareSerial Serial0(0); HardwareSerial Serial0(0);
@ -48,64 +45,43 @@ HardwareSerial Serial1(1);
#if SOC_UART_NUM > 2 #if SOC_UART_NUM > 2
HardwareSerial Serial2(2); HardwareSerial Serial2(2);
#endif #endif
#if SOC_UART_NUM > 3
HardwareSerial Serial3(3);
#endif
#if SOC_UART_NUM > 4
HardwareSerial Serial4(4);
#endif
#if (SOC_UART_NUM > 5)
HardwareSerial Serial5(5);
#endif
#if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event #if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event
extern void HWCDCSerialEvent(void) __attribute__((weak)); extern void HWCDCSerialEvent(void) __attribute__((weak));
void HWCDCSerialEvent(void) {}
#endif #endif
#if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event #if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event
// Used by Hardware Serial for USB CDC events // Used by Hardware Serial for USB CDC events
extern void USBSerialEvent(void) __attribute__((weak)); extern void USBSerialEvent(void) __attribute__((weak));
void USBSerialEvent(void) {}
#endif #endif
void serialEventRun(void) { void serialEventRun(void) {
#if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event #if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event
if (HWCDCSerialEvent && HWCDCSerial.available()) { if (HWCDCSerial.available()) {
HWCDCSerialEvent(); HWCDCSerialEvent();
} }
#endif #endif
#if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event #if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event
if (USBSerialEvent && USBSerial.available()) { if (USBSerial.available()) {
USBSerialEvent(); USBSerialEvent();
} }
#endif #endif
// UART0 is default serialEvent() // UART0 is default serialEvent()
if (serialEvent && Serial0.available()) { if (Serial0.available()) {
serialEvent(); serialEvent();
} }
#if SOC_UART_NUM > 1 #if SOC_UART_NUM > 1
if (serialEvent1 && Serial1.available()) { if (Serial1.available()) {
serialEvent1(); serialEvent1();
} }
#endif #endif
#if SOC_UART_NUM > 2 #if SOC_UART_NUM > 2
if (serialEvent2 && Serial2.available()) { if (Serial2.available()) {
serialEvent2(); serialEvent2();
} }
#endif #endif
#if SOC_UART_NUM > 3
if (serialEvent3 && Serial3.available()) {
serialEvent3();
}
#endif
#if SOC_UART_NUM > 4
if (serialEvent4 && Serial4.available()) {
serialEvent4();
}
#endif
#if SOC_UART_NUM > 5
if (serialEvent5 && Serial5.available()) {
serialEvent5();
}
#endif
} }
#endif #endif
@ -190,8 +166,7 @@ void HardwareSerial::onReceive(OnReceiveCb function, bool onlyOnTimeout) {
// in case that onReceive() shall work only with RX Timeout, FIFO shall be high // in case that onReceive() shall work only with RX Timeout, FIFO shall be high
// this is a work around for an IDF issue with events and low FIFO Full value (< 3) // this is a work around for an IDF issue with events and low FIFO Full value (< 3)
// Not valid for the LP UART if (_onReceiveTimeout) {
if (_onReceiveTimeout && _uart_nr < SOC_UART_HP_NUM) {
uartSetRxFIFOFull(_uart, 120); uartSetRxFIFOFull(_uart, 120);
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes."); log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
} }
@ -213,13 +188,12 @@ bool HardwareSerial::setRxFIFOFull(uint8_t fifoBytes) {
HSERIAL_MUTEX_LOCK(); HSERIAL_MUTEX_LOCK();
// in case that onReceive() shall work only with RX Timeout, FIFO shall be high // in case that onReceive() shall work only with RX Timeout, FIFO shall be high
// this is a work around for an IDF issue with events and low FIFO Full value (< 3) // this is a work around for an IDF issue with events and low FIFO Full value (< 3)
// Not valid for the LP UART if (_onReceiveCB != NULL && _onReceiveTimeout) {
if (_onReceiveCB != NULL && _onReceiveTimeout && _uart_nr < SOC_UART_HP_NUM) {
fifoBytes = 120; fifoBytes = 120;
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes."); log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
} }
bool retCode = uartSetRxFIFOFull(_uart, fifoBytes); // Set new timeout bool retCode = uartSetRxFIFOFull(_uart, fifoBytes); // Set new timeout
if (fifoBytes > 0 && fifoBytes < UART_HW_FIFO_LEN(_uart_nr) - 1) { if (fifoBytes > 0 && fifoBytes < SOC_UART_FIFO_LEN - 1) {
_rxFIFOFull = fifoBytes; _rxFIFOFull = fifoBytes;
} }
HSERIAL_MUTEX_UNLOCK(); HSERIAL_MUTEX_UNLOCK();
@ -317,15 +291,6 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
} }
#endif #endif
// map logical pins to GPIO numbers
rxPin = digitalPinToGPIONumber(rxPin);
txPin = digitalPinToGPIONumber(txPin);
int8_t _rxPin = uart_get_RxPin(_uart_nr);
int8_t _txPin = uart_get_TxPin(_uart_nr);
rxPin = rxPin < 0 ? _rxPin : rxPin;
txPin = txPin < 0 ? _txPin : txPin;
HSERIAL_MUTEX_LOCK(); HSERIAL_MUTEX_LOCK();
// First Time or after end() --> set default Pins // First Time or after end() --> set default Pins
if (!uartIsDriverInstalled(_uart)) { if (!uartIsDriverInstalled(_uart)) {
@ -340,7 +305,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
txPin = _txPin < 0 ? (int8_t)SOC_TX0 : _txPin; txPin = _txPin < 0 ? (int8_t)SOC_TX0 : _txPin;
} }
break; break;
#if SOC_UART_HP_NUM > 1 #if SOC_UART_NUM > 1 // may save some flash bytes...
case UART_NUM_1: case UART_NUM_1:
if (rxPin < 0 && txPin < 0) { if (rxPin < 0 && txPin < 0) {
// do not change RX1/TX1 if it has already been set before // do not change RX1/TX1 if it has already been set before
@ -348,69 +313,22 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
txPin = _txPin < 0 ? (int8_t)TX1 : _txPin; txPin = _txPin < 0 ? (int8_t)TX1 : _txPin;
} }
break; break;
#endif // UART_NUM_1 #endif
#if SOC_UART_HP_NUM > 2 #if SOC_UART_NUM > 2 // may save some flash bytes...
case UART_NUM_2: case UART_NUM_2:
if (rxPin < 0 && txPin < 0) { if (rxPin < 0 && txPin < 0) {
// do not change RX2/TX2 if it has already been set before // do not change RX2/TX2 if it has already been set before
#ifdef RX2
rxPin = _rxPin < 0 ? (int8_t)RX2 : _rxPin; rxPin = _rxPin < 0 ? (int8_t)RX2 : _rxPin;
#endif
#ifdef TX2
txPin = _txPin < 0 ? (int8_t)TX2 : _txPin; txPin = _txPin < 0 ? (int8_t)TX2 : _txPin;
#endif
} }
break; break;
#endif // UART_NUM_2
#if SOC_UART_HP_NUM > 3
case UART_NUM_3:
if (rxPin < 0 && txPin < 0) {
// do not change RX3/TX3 if it has already been set before
#ifdef RX3
rxPin = _rxPin < 0 ? (int8_t)RX3 : _rxPin;
#endif #endif
#ifdef TX3
txPin = _txPin < 0 ? (int8_t)TX3 : _txPin;
#endif
}
break;
#endif // UART_NUM_3
#if SOC_UART_HP_NUM > 4
case UART_NUM_4:
if (rxPin < 0 && txPin < 0) {
// do not change RX4/TX4 if it has already been set before
#ifdef RX4
rxPin = _rxPin < 0 ? (int8_t)RX4 : _rxPin;
#endif
#ifdef TX4
txPin = _txPin < 0 ? (int8_t)TX4 : _txPin;
#endif
}
break;
#endif // UART_NUM_4
#if (SOC_UART_LP_NUM >= 1)
case LP_UART_NUM_0:
if (rxPin < 0 && txPin < 0) {
// do not change RX0_LP/TX0_LP if it has already been set before
#ifdef LP_RX0
rxPin = _rxPin < 0 ? (int8_t)LP_RX0 : _rxPin;
#endif
#ifdef LP_TX0
txPin = _txPin < 0 ? (int8_t)LP_TX0 : _txPin;
#endif
}
break;
#endif // LP_UART_NUM_0
} }
} }
// if no RX/TX pins are defined, it will not start the UART driver // map logical pins to GPIO numbers
if (rxPin < 0 && txPin < 0) { rxPin = digitalPinToGPIONumber(rxPin);
log_e("No RX/TX pins defined. Please set RX/TX pins."); txPin = digitalPinToGPIONumber(txPin);
HSERIAL_MUTEX_UNLOCK();
return;
}
// IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified. // IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified.
// it will detach previous UART attached pins // it will detach previous UART attached pins
@ -465,8 +383,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
if (!_rxFIFOFull) { // it has not being changed before calling begin() if (!_rxFIFOFull) { // it has not being changed before calling begin()
// set a default FIFO Full value for the IDF driver // set a default FIFO Full value for the IDF driver
uint8_t fifoFull = 1; uint8_t fifoFull = 1;
// if baud rate is higher than 57600 or onReceive() is set, it will set FIFO Full to 120 bytes, except for LP UART if (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout)) {
if (_uart_nr < SOC_UART_HP_NUM && (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout))) {
fifoFull = 120; fifoFull = 120;
} }
uartSetRxFIFOFull(_uart, fifoFull); uartSetRxFIFOFull(_uart, fifoFull);
@ -498,12 +415,6 @@ void HardwareSerial::setDebugOutput(bool en) {
if (_uart == 0) { if (_uart == 0) {
return; return;
} }
#if (SOC_UART_LP_NUM >= 1)
if (_uart_nr >= SOC_UART_HP_NUM) {
log_e("LP UART does not support Debug Output.");
return;
}
#endif
if (en) { if (en) {
uartSetDebug(_uart); uartSetDebug(_uart);
} else { } else {
@ -607,56 +518,35 @@ bool HardwareSerial::setMode(SerialMode mode) {
return uartSetMode(_uart, mode); return uartSetMode(_uart, mode);
} }
// Sets the UART Clock Source based on the compatible SoC options
// This method must be called before starting UART using begin(), otherwise it won't have any effect.
// Clock Source Options are:
// UART_CLK_SRC_DEFAULT :: any SoC - it will set whatever IDF defines as the default UART Clock Source
// UART_CLK_SRC_APB :: ESP32, ESP32-S2, ESP32-C3 and ESP32-S3
// UART_CLK_SRC_PLL :: ESP32-C2, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2 and ESP32-P4
// UART_CLK_SRC_XTAL :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4
// UART_CLK_SRC_RTC :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4
// UART_CLK_SRC_REF_TICK :: ESP32 and ESP32-S2
// Note: CLK_SRC_PLL Freq depends on the SoC - ESP32-C2 has 40MHz, ESP32-H2 has 48MHz and ESP32-C5, C6, C61 and P4 has 80MHz
// Note: ESP32-C6, C61, ESP32-P4 and ESP32-C5 have LP UART that will use only RTC_FAST or XTAL/2 as Clock Source
bool HardwareSerial::setClockSource(SerialClkSrc clkSrc) {
if (_uart) {
log_e("No Clock Source change was done. This function must be called before beginning UART%d.", _uart_nr);
return false;
}
return uartSetClockSource(_uart_nr, (uart_sclk_t)clkSrc);
}
// minimum total RX Buffer size is the UART FIFO space (128 bytes for most SoC) + 1. IDF imposition. // minimum total RX Buffer size is the UART FIFO space (128 bytes for most SoC) + 1. IDF imposition.
// LP UART has FIFO of 16 bytes
size_t HardwareSerial::setRxBufferSize(size_t new_size) { size_t HardwareSerial::setRxBufferSize(size_t new_size) {
if (_uart) { if (_uart) {
log_e("RX Buffer can't be resized when Serial is already running. Set it before calling begin()."); log_e("RX Buffer can't be resized when Serial is already running. Set it before calling begin().");
return 0; return 0;
} }
uint8_t FIFOLen = UART_HW_FIFO_LEN(_uart_nr);
// Valid value is higher than the FIFO length if (new_size <= SOC_UART_FIFO_LEN) {
if (new_size <= FIFOLen) { log_w("RX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN + 1); // ESP32, S2, S3 and C3 means higher than 128
new_size = FIFOLen + 1; new_size = SOC_UART_FIFO_LEN + 1;
log_w("RX Buffer set to minimum value: %d.", new_size);
} }
_rxBufferSize = new_size; _rxBufferSize = new_size;
return _rxBufferSize; return _rxBufferSize;
} }
// minimum total TX Buffer size is the UART FIFO space (128 bytes for most SoC) + 1. // minimum total TX Buffer size is the UART FIFO space (128 bytes for most SoC).
// LP UART has FIFO of 16 bytes
size_t HardwareSerial::setTxBufferSize(size_t new_size) { size_t HardwareSerial::setTxBufferSize(size_t new_size) {
if (_uart) { if (_uart) {
log_e("TX Buffer can't be resized when Serial is already running. Set it before calling begin()."); log_e("TX Buffer can't be resized when Serial is already running. Set it before calling begin().");
return 0; return 0;
} }
uint8_t FIFOLen = UART_HW_FIFO_LEN(_uart_nr);
// Valid values are zero or higher than the FIFO length if (new_size <= SOC_UART_FIFO_LEN) {
if (new_size > 0 && new_size <= FIFOLen) { log_w("TX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN); // ESP32, S2, S3 and C3 means higher than 128
new_size = FIFOLen + 1; _txBufferSize = 0; // it will use just UART FIFO with SOC_UART_FIFO_LEN bytes (128 for most SoC)
log_w("TX Buffer set to minimum value: %d.", new_size); return SOC_UART_FIFO_LEN;
} }
// if new_size is higher than SOC_UART_FIFO_LEN, TX Ringbuffer will be active and it will be used to report back "availableToWrite()" // if new_size is higher than SOC_UART_FIFO_LEN, TX Ringbuffer will be active and it will be used to report back "availableToWrite()"
_txBufferSize = new_size; _txBufferSize = new_size;

View file

@ -96,51 +96,16 @@ typedef enum {
UART_PARITY_ERROR UART_PARITY_ERROR
} hardwareSerial_error_t; } hardwareSerial_error_t;
typedef enum {
UART_CLK_SRC_DEFAULT = UART_SCLK_DEFAULT,
#if SOC_UART_SUPPORT_APB_CLK
UART_CLK_SRC_APB = UART_SCLK_APB,
#endif
#if SOC_UART_SUPPORT_PLL_F40M_CLK
UART_CLK_SRC_PLL = UART_SCLK_PLL_F40M,
#elif SOC_UART_SUPPORT_PLL_F80M_CLK
UART_CLK_SRC_PLL = UART_SCLK_PLL_F80M,
#elif CONFIG_IDF_TARGET_ESP32H2
UART_CLK_SRC_PLL = UART_SCLK_PLL_F48M,
#endif
#if SOC_UART_SUPPORT_XTAL_CLK
UART_CLK_SRC_XTAL = UART_SCLK_XTAL,
#endif
#if SOC_UART_SUPPORT_RTC_CLK
UART_CLK_SRC_RTC = UART_SCLK_RTC,
#endif
#if SOC_UART_SUPPORT_REF_TICK
UART_CLK_SRC_REF_TICK = UART_SCLK_REF_TICK,
#endif
} SerialClkSrc;
#ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE #ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048 #define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048
#else
#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE CONFIG_ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
#endif
#endif #endif
#ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY #ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY
#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_PRIORITY
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES - 1) #define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES - 1)
#else
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY CONFIG_ARDUINO_SERIAL_EVENT_TASK_PRIORITY
#endif
#endif #endif
#ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE #ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1 #define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1
#else
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE CONFIG_ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
#endif
#endif #endif
// UART0 pins are defined by default by the bootloader. // UART0 pins are defined by default by the bootloader.
@ -160,10 +125,6 @@ typedef enum {
#define SOC_RX0 (gpio_num_t)17 #define SOC_RX0 (gpio_num_t)17
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#define SOC_RX0 (gpio_num_t)23 #define SOC_RX0 (gpio_num_t)23
#elif CONFIG_IDF_TARGET_ESP32P4
#define SOC_RX0 (gpio_num_t)38
#elif CONFIG_IDF_TARGET_ESP32C5
#define SOC_RX0 (gpio_num_t)12
#endif #endif
#endif #endif
@ -180,16 +141,12 @@ typedef enum {
#define SOC_TX0 (gpio_num_t)16 #define SOC_TX0 (gpio_num_t)16
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#define SOC_TX0 (gpio_num_t)24 #define SOC_TX0 (gpio_num_t)24
#elif CONFIG_IDF_TARGET_ESP32P4
#define SOC_TX0 (gpio_num_t)37
#elif CONFIG_IDF_TARGET_ESP32C5
#define SOC_TX0 (gpio_num_t)11
#endif #endif
#endif #endif
// Default pins for UART1 are arbitrary, and defined here for convenience. // Default pins for UART1 are arbitrary, and defined here for convenience.
#if SOC_UART_HP_NUM > 1 #if SOC_UART_NUM > 1
#ifndef RX1 #ifndef RX1
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
#define RX1 (gpio_num_t)26 #define RX1 (gpio_num_t)26
@ -205,10 +162,6 @@ typedef enum {
#define RX1 (gpio_num_t)4 #define RX1 (gpio_num_t)4
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#define RX1 (gpio_num_t)0 #define RX1 (gpio_num_t)0
#elif CONFIG_IDF_TARGET_ESP32P4
#define RX1 (gpio_num_t)11
#elif CONFIG_IDF_TARGET_ESP32C5
#define RX1 (gpio_num_t)4
#endif #endif
#endif #endif
@ -227,17 +180,13 @@ typedef enum {
#define TX1 (gpio_num_t)5 #define TX1 (gpio_num_t)5
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#define TX1 (gpio_num_t)1 #define TX1 (gpio_num_t)1
#elif CONFIG_IDF_TARGET_ESP32P4
#define TX1 (gpio_num_t)10
#elif CONFIG_IDF_TARGET_ESP32C5
#define TX1 (gpio_num_t)5
#endif #endif
#endif #endif
#endif /* SOC_UART_HP_NUM > 1 */ #endif /* SOC_UART_NUM > 1 */
// Default pins for UART2 are arbitrary, and defined here for convenience. // Default pins for UART2 are arbitrary, and defined here for convenience.
#if SOC_UART_HP_NUM > 2 #if SOC_UART_NUM > 2
#ifndef RX2 #ifndef RX2
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
#define RX2 (gpio_num_t)4 #define RX2 (gpio_num_t)4
@ -253,17 +202,7 @@ typedef enum {
#define TX2 (gpio_num_t)20 #define TX2 (gpio_num_t)20
#endif #endif
#endif #endif
#endif /* SOC_UART_HP_NUM > 2 */ #endif /* SOC_UART_NUM > 2 */
#if SOC_UART_LP_NUM >= 1
#ifndef LP_RX0
#define LP_RX0 (gpio_num_t) LP_U0RXD_GPIO_NUM
#endif
#ifndef LP_TX0
#define LP_TX0 (gpio_num_t) LP_U0TXD_GPIO_NUM
#endif
#endif /* SOC_UART_LP_NUM >= 1 */
typedef std::function<void(void)> OnReceiveCb; typedef std::function<void(void)> OnReceiveCb;
typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb; typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb;
@ -312,7 +251,7 @@ public:
// rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127) // rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127)
void begin( void begin(
unsigned long baud, uint32_t config = SERIAL_8N1, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false, unsigned long timeout_ms = 20000UL, unsigned long baud, uint32_t config = SERIAL_8N1, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false, unsigned long timeout_ms = 20000UL,
uint8_t rxfifo_full_thrhd = 120 uint8_t rxfifo_full_thrhd = 112
); );
void end(void); void end(void);
void updateBaudRate(unsigned long baud); void updateBaudRate(unsigned long baud);
@ -375,17 +314,6 @@ public:
// UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes) // UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes)
// UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes) // UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes)
bool setMode(SerialMode mode); bool setMode(SerialMode mode);
// Used to set the UART clock source mode. It must be set before calling begin(), otherwise it won't have any effect.
// Not all clock source are available to every SoC. The compatible option are listed here:
// UART_CLK_SRC_DEFAULT :: any SoC - it will set whatever IDF defines as the default UART Clock Source
// UART_CLK_SRC_APB :: ESP32, ESP32-S2, ESP32-C3 and ESP32-S3
// UART_CLK_SRC_PLL :: ESP32-C2, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2 and ESP32-P4
// UART_CLK_SRC_XTAL :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4
// UART_CLK_SRC_RTC :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4
// UART_CLK_SRC_REF_TICK :: ESP32 and ESP32-S2
// Note: CLK_SRC_PLL Freq depends on the SoC - ESP32-C2 has 40MHz, ESP32-H2 has 48MHz and ESP32-C5, C6, C61 and P4 has 80MHz
// Note: ESP32-C6, C61, ESP32-P4 and ESP32-C5 have LP UART that will use only RTC_FAST or XTAL/2 as Clock Source
bool setClockSource(SerialClkSrc clkSrc);
size_t setRxBufferSize(size_t new_size); size_t setRxBufferSize(size_t new_size);
size_t setTxBufferSize(size_t new_size); size_t setTxBufferSize(size_t new_size);
@ -435,15 +363,6 @@ extern HardwareSerial Serial1;
#if SOC_UART_NUM > 2 #if SOC_UART_NUM > 2
extern HardwareSerial Serial2; extern HardwareSerial Serial2;
#endif #endif
#if SOC_UART_NUM > 3
extern HardwareSerial Serial3;
#endif
#if SOC_UART_NUM > 4
extern HardwareSerial Serial4;
#endif
#if SOC_UART_NUM > 5
extern HardwareSerial Serial5;
#endif
#endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) #endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
#endif // HardwareSerial_h #endif // HardwareSerial_h

View file

@ -22,10 +22,6 @@
#include "lwip/netif.h" #include "lwip/netif.h"
#include "StreamString.h" #include "StreamString.h"
#ifndef CONFIG_LWIP_IPV6
#define IP6_NO_ZONE 0
#endif
IPAddress::IPAddress() : IPAddress(IPv4) {} IPAddress::IPAddress() : IPAddress(IPv4) {}
IPAddress::IPAddress(IPType ip_type) { IPAddress::IPAddress(IPType ip_type) {
@ -205,13 +201,7 @@ bool IPAddress::fromString6(const char *address) {
colons++; colons++;
acc = 0; acc = 0;
} else if (c == '%') { } else if (c == '%') {
// netif_index_to_name crashes on latest esp-idf _zone = netif_name_to_index(address);
// _zone = netif_name_to_index(address);
// in the interim, we parse the suffix as a zone number
while ((*address != '\0') && (!isdigit(*address))) { // skip all non-digit after '%'
address++;
}
_zone = atol(address) + 1; // increase by one by convention, so we can have zone '0'
while (*address != '\0') { while (*address != '\0') {
address++; address++;
} }
@ -354,25 +344,12 @@ size_t IPAddress::printTo(Print &p, bool includeZone) const {
n += p.print(':'); n += p.print(':');
} }
} }
// add a zone if zone-id is non-zero (causes exception on recent IDF builds) // add a zone if zone-id is non-zero
// if (_zone > 0 && includeZone) {
// n += p.print('%');
// char if_name[NETIF_NAMESIZE];
// netif_index_to_name(_zone, if_name);
// n += p.print(if_name);
// }
// In the interim, we just output the index number
if (_zone > 0 && includeZone) { if (_zone > 0 && includeZone) {
n += p.print('%'); n += p.print('%');
// look for the interface name char if_name[NETIF_NAMESIZE];
for (netif *intf = netif_list; intf != nullptr; intf = intf->next) { netif_index_to_name(_zone, if_name);
if (_zone - 1 == intf->num) { n += p.print(if_name);
n += p.print(intf->name[0]);
n += p.print(intf->name[1]);
break;
}
}
n += p.print(_zone - 1);
} }
return n; return n;
} }
@ -391,7 +368,6 @@ IPAddress::IPAddress(const ip_addr_t *addr) {
} }
void IPAddress::to_ip_addr_t(ip_addr_t *addr) const { void IPAddress::to_ip_addr_t(ip_addr_t *addr) const {
#if CONFIG_LWIP_IPV6
if (_type == IPv6) { if (_type == IPv6) {
addr->type = IPADDR_TYPE_V6; addr->type = IPADDR_TYPE_V6;
addr->u_addr.ip6.addr[0] = _address.dword[0]; addr->u_addr.ip6.addr[0] = _address.dword[0];
@ -405,13 +381,9 @@ void IPAddress::to_ip_addr_t(ip_addr_t *addr) const {
addr->type = IPADDR_TYPE_V4; addr->type = IPADDR_TYPE_V4;
addr->u_addr.ip4.addr = _address.dword[IPADDRESS_V4_DWORD_INDEX]; addr->u_addr.ip4.addr = _address.dword[IPADDRESS_V4_DWORD_INDEX];
} }
#else
addr->addr = _address.dword[IPADDRESS_V4_DWORD_INDEX];
#endif
} }
IPAddress &IPAddress::from_ip_addr_t(const ip_addr_t *addr) { IPAddress &IPAddress::from_ip_addr_t(const ip_addr_t *addr) {
#if CONFIG_LWIP_IPV6
if (addr->type == IPADDR_TYPE_V6) { if (addr->type == IPADDR_TYPE_V6) {
_type = IPv6; _type = IPv6;
_address.dword[0] = addr->u_addr.ip6.addr[0]; _address.dword[0] = addr->u_addr.ip6.addr[0];
@ -422,21 +394,13 @@ IPAddress &IPAddress::from_ip_addr_t(const ip_addr_t *addr) {
_zone = addr->u_addr.ip6.zone; _zone = addr->u_addr.ip6.zone;
#endif /* LWIP_IPV6_SCOPES */ #endif /* LWIP_IPV6_SCOPES */
} else { } else {
#endif
_type = IPv4; _type = IPv4;
memset(_address.bytes, 0, sizeof(_address.bytes)); memset(_address.bytes, 0, sizeof(_address.bytes));
#if CONFIG_LWIP_IPV6
_address.dword[IPADDRESS_V4_DWORD_INDEX] = addr->u_addr.ip4.addr; _address.dword[IPADDRESS_V4_DWORD_INDEX] = addr->u_addr.ip4.addr;
#else
_address.dword[IPADDRESS_V4_DWORD_INDEX] = addr->addr;
#endif
#if CONFIG_LWIP_IPV6
} }
#endif
return *this; return *this;
} }
#if CONFIG_LWIP_IPV6
esp_ip6_addr_type_t IPAddress::addr_type() const { esp_ip6_addr_type_t IPAddress::addr_type() const {
if (_type != IPv6) { if (_type != IPv6) {
return ESP_IP6_ADDR_IS_UNKNOWN; return ESP_IP6_ADDR_IS_UNKNOWN;
@ -445,9 +409,6 @@ esp_ip6_addr_type_t IPAddress::addr_type() const {
to_ip_addr_t(&addr); to_ip_addr_t(&addr);
return esp_netif_ip6_get_addr_type((esp_ip6_addr_t *)(&(addr.u_addr.ip6))); return esp_netif_ip6_get_addr_type((esp_ip6_addr_t *)(&(addr.u_addr.ip6)));
} }
#endif
#if CONFIG_LWIP_IPV6
const IPAddress IN6ADDR_ANY(IPv6); const IPAddress IN6ADDR_ANY(IPv6);
#endif
const IPAddress INADDR_NONE(0, 0, 0, 0); const IPAddress INADDR_NONE(0, 0, 0, 0);

View file

@ -24,7 +24,6 @@
#include "WString.h" #include "WString.h"
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "esp_netif_ip_addr.h" #include "esp_netif_ip_addr.h"
#include "sdkconfig.h"
#define IPADDRESS_V4_BYTES_INDEX 12 #define IPADDRESS_V4_BYTES_INDEX 12
#define IPADDRESS_V4_DWORD_INDEX 3 #define IPADDRESS_V4_DWORD_INDEX 3
@ -116,9 +115,7 @@ public:
IPAddress(const ip_addr_t *addr); IPAddress(const ip_addr_t *addr);
void to_ip_addr_t(ip_addr_t *addr) const; void to_ip_addr_t(ip_addr_t *addr) const;
IPAddress &from_ip_addr_t(const ip_addr_t *addr); IPAddress &from_ip_addr_t(const ip_addr_t *addr);
#if CONFIG_LWIP_IPV6
esp_ip6_addr_type_t addr_type() const; esp_ip6_addr_type_t addr_type() const;
#endif
uint8_t zone() const { uint8_t zone() const {
return (type() == IPv6) ? _zone : 0; return (type() == IPv6) ? _zone : 0;
} }

View file

@ -18,14 +18,14 @@
Created July 2011 Created July 2011
parsing functions based on TextFinder library by Michael Margolis parsing functions based on TextFinder library by Michael Margolis
findMulti/findUntil routines written by Jim Leonard/Xuth
*/ */
#include "Arduino.h" #include "Arduino.h"
#include "Stream.h" #include "Stream.h"
#include "esp32-hal.h"
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait #define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
// private method to read stream with timeout // private method to read stream with timeout
int Stream::timedRead() { int Stream::timedRead() {
@ -55,26 +55,18 @@ int Stream::timedPeek() {
// returns peek of the next digit in the stream or -1 if timeout // returns peek of the next digit in the stream or -1 if timeout
// discards non-numeric characters // discards non-numeric characters
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) { int Stream::peekNextDigit() {
int c; int c;
while (1) { while (1) {
c = timedPeek(); c = timedPeek();
if (c < 0) {
if (c < 0 || c == '-' || (c >= '0' && c <= '9') || (detectDecimal && c == '.')) { return c; // timeout
}
if (c == '-') {
return c; return c;
} }
if (c >= '0' && c <= '9') {
switch (lookahead) { return c;
case SKIP_NONE: return -1; // Fail code.
case SKIP_WHITESPACE:
switch (c) {
case ' ':
case '\t':
case '\r':
case '\n': break;
default: return -1; // Fail code.
}
case SKIP_ALL: break;
} }
read(); // discard non-numeric read(); // discard non-numeric
} }
@ -87,6 +79,9 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
{ {
_timeout = timeout; _timeout = timeout;
} }
unsigned long Stream::getTimeout(void) {
return _timeout;
}
// find returns true if the target string is found // find returns true if the target string is found
bool Stream::find(const char *target) { bool Stream::find(const char *target) {
@ -110,142 +105,13 @@ bool Stream::findUntil(const char *target, const char *terminator) {
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) { bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) {
if (terminator == NULL) { if (terminator == NULL) {
MultiTarget t[1] = {{target, targetLen, 0}}; MultiTarget t[1] = {{target, targetLen, 0}};
return findMulti(t, 1) == 0; return findMulti(t, 1) == 0 ? true : false;
} else { } else {
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}}; MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
return findMulti(t, 2) == 0; return findMulti(t, 2) == 0 ? true : false;
} }
} }
// returns the first valid (long) integer value from the current position.
// lookahead determines how parseInt looks ahead in the stream.
// See LookaheadMode enumeration at the top of the file.
// Lookahead is terminated by the first character that is not a valid part of an integer.
// Once parsing commences, 'ignore' will be skipped in the stream.
long Stream::parseInt(LookaheadMode lookahead, char ignore) {
bool isNegative = false;
long value = 0;
int c;
c = peekNextDigit(lookahead, false);
// ignore non numeric leading characters
if (c < 0) {
return 0; // zero returned if timeout
}
do {
if ((char)c == ignore)
; // ignore this character
else if (c == '-') {
isNegative = true;
} else if (c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0';
}
read(); // consume the character we got with peek
c = timedPeek();
} while ((c >= '0' && c <= '9') || (char)c == ignore);
if (isNegative) {
value = -value;
}
return value;
}
// as parseInt but returns a floating point value
float Stream::parseFloat(LookaheadMode lookahead, char ignore) {
bool isNegative = false;
bool isFraction = false;
double value = 0.0;
int c;
double fraction = 1.0;
c = peekNextDigit(lookahead, true);
// ignore non numeric leading characters
if (c < 0) {
return 0; // zero returned if timeout
}
do {
if ((char)c == ignore)
; // ignore
else if (c == '-') {
isNegative = true;
} else if (c == '.') {
isFraction = true;
} else if (c >= '0' && c <= '9') { // is c a digit?
if (isFraction) {
fraction *= 0.1;
value = value + fraction * (c - '0');
} else {
value = value * 10 + c - '0';
}
}
read(); // consume the character we got with peek
c = timedPeek();
} while ((c >= '0' && c <= '9') || (c == '.' && !isFraction) || (char)c == ignore);
if (isNegative) {
value = -value;
}
return value;
}
// read characters from stream into buffer
// terminates if length characters have been read, or timeout (see setTimeout)
// returns the number of characters placed in the buffer
// the buffer is NOT null terminated.
//
size_t Stream::readBytes(char *buffer, size_t length) {
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0) {
break;
}
*buffer++ = (char)c;
count++;
}
return count;
}
// as readBytes with terminator character
// terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found)
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) {
size_t index = 0;
while (index < length) {
int c = timedRead();
if (c < 0 || (char)c == terminator) {
break;
}
*buffer++ = (char)c;
index++;
}
return index; // return number of characters, not including null terminator
}
String Stream::readString() {
String ret;
int c = timedRead();
while (c >= 0) {
ret += (char)c;
c = timedRead();
}
return ret;
}
String Stream::readStringUntil(char terminator) {
String ret;
int c = timedRead();
while (c >= 0 && (char)c != terminator) {
ret += (char)c;
c = timedRead();
}
return ret;
}
int Stream::findMulti(struct Stream::MultiTarget *targets, int tCount) { int Stream::findMulti(struct Stream::MultiTarget *targets, int tCount) {
// any zero length target string automatically matches and would make // any zero length target string automatically matches and would make
// a mess of the rest of the algorithm. // a mess of the rest of the algorithm.
@ -263,7 +129,7 @@ int Stream::findMulti(struct Stream::MultiTarget *targets, int tCount) {
for (struct MultiTarget *t = targets; t < targets + tCount; ++t) { for (struct MultiTarget *t = targets; t < targets + tCount; ++t) {
// the simple case is if we match, deal with that first. // the simple case is if we match, deal with that first.
if ((char)c == t->str[t->index]) { if (c == t->str[t->index]) {
if (++t->index == t->len) { if (++t->index == t->len) {
return t - targets; return t - targets;
} else { } else {
@ -283,7 +149,7 @@ int Stream::findMulti(struct Stream::MultiTarget *targets, int tCount) {
do { do {
--t->index; --t->index;
// first check if current char works against the new current index // first check if current char works against the new current index
if ((char)c != t->str[t->index]) { if (c != t->str[t->index]) {
continue; continue;
} }
@ -316,3 +182,146 @@ int Stream::findMulti(struct Stream::MultiTarget *targets, int tCount) {
// unreachable // unreachable
return -1; return -1;
} }
// returns the first valid (long) integer value from the current position.
// initial characters that are not digits (or the minus sign) are skipped
// function is terminated by the first character that is not a digit.
long Stream::parseInt() {
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
}
// as above but a given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored
long Stream::parseInt(char skipChar) {
boolean isNegative = false;
long value = 0;
int c;
c = peekNextDigit();
// ignore non numeric leading characters
if (c < 0) {
return 0; // zero returned if timeout
}
do {
if (c == skipChar) {
} // ignore this character
else if (c == '-') {
isNegative = true;
} else if (c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0';
}
read(); // consume the character we got with peek
c = timedPeek();
} while ((c >= '0' && c <= '9') || c == skipChar);
if (isNegative) {
value = -value;
}
return value;
}
// as parseInt but returns a floating point value
float Stream::parseFloat() {
return parseFloat(NO_SKIP_CHAR);
}
// as above but the given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored
float Stream::parseFloat(char skipChar) {
boolean isNegative = false;
boolean isFraction = false;
long value = 0;
int c;
float fraction = 1.0;
c = peekNextDigit();
// ignore non numeric leading characters
if (c < 0) {
return 0; // zero returned if timeout
}
do {
if (c == skipChar) {
} // ignore
else if (c == '-') {
isNegative = true;
} else if (c == '.') {
isFraction = true;
} else if (c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0';
if (isFraction) {
fraction *= 0.1f;
}
}
read(); // consume the character we got with peek
c = timedPeek();
} while ((c >= '0' && c <= '9') || c == '.' || c == skipChar);
if (isNegative) {
value = -value;
}
if (isFraction) {
return value * fraction;
} else {
return value;
}
}
// read characters from stream into buffer
// terminates if length characters have been read, or timeout (see setTimeout)
// returns the number of characters placed in the buffer
// the buffer is NOT null terminated.
//
size_t Stream::readBytes(char *buffer, size_t length) {
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0) {
break;
}
*buffer++ = (char)c;
count++;
}
return count;
}
// as readBytes with terminator character
// terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found)
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) {
if (length < 1) {
return 0;
}
size_t index = 0;
while (index < length) {
int c = timedRead();
if (c < 0 || c == terminator) {
break;
}
*buffer++ = (char)c;
index++;
}
return index; // return number of characters, not including null terminator
}
String Stream::readString() {
String ret;
int c = timedRead();
while (c >= 0) {
ret += (char)c;
c = timedRead();
}
return ret;
}
String Stream::readStringUntil(char terminator) {
String ret;
int c = timedRead();
while (c >= 0 && c != terminator) {
ret += (char)c;
c = timedRead();
}
return ret;
}

View file

@ -1,83 +1,72 @@
/* /*
Stream.h - base class for character-based streams. Stream.h - base class for character-based streams.
Copyright (c) 2010 David A. Mellis. All right reserved. Copyright (c) 2010 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
parsing functions based on TextFinder library by Michael Margolis parsing functions based on TextFinder library by Michael Margolis
*/ */
#pragma once #ifndef Stream_h
#define Stream_h
#include <inttypes.h> #include <inttypes.h>
#include "Print.h" #include "Print.h"
// compatibility macros for testing // compatibility macros for testing
/* /*
#define getInt() parseInt() #define getInt() parseInt()
#define getInt(ignore) parseInt(ignore) #define getInt(skipChar) parseInt(skipchar)
#define getFloat() parseFloat() #define getFloat() parseFloat()
#define getFloat(ignore) parseFloat(ignore) #define getFloat(skipChar) parseFloat(skipChar)
#define getString( pre_string, post_string, buffer, length) #define getString( pre_string, post_string, buffer, length)
readBytesBetween( pre_string, terminator, buffer, length) readBytesBetween( pre_string, terminator, buffer, length)
*/ */
// This enumeration provides the lookahead options for parseInt(), parseFloat()
// The rules set out here are used until either the first valid character is found
// or a time out occurs due to lack of input.
enum LookaheadMode {
SKIP_ALL, // All invalid characters are ignored.
SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid.
SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped.
};
#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field
class Stream : public Print { class Stream : public Print {
protected: protected:
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
unsigned long _startMillis; // used for timeout measurement unsigned long _startMillis; // used for timeout measurement
int timedRead(); // private method to read stream with timeout int timedRead(); // private method to read stream with timeout
int timedPeek(); // private method to peek stream with timeout int timedPeek(); // private method to peek stream with timeout
int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
public: public:
virtual int available() = 0; virtual int available() = 0;
virtual int read() = 0; virtual int read() = 0;
virtual int peek() = 0; virtual int peek() = 0;
Stream() { Stream() : _startMillis(0) {
_timeout = 1000; _timeout = 1000;
} }
virtual ~Stream() {}
// parsing methods // parsing methods
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
unsigned long getTimeout(void) { unsigned long getTimeout(void);
return _timeout;
}
bool find(const char *target); // reads data from the stream until the target string is found bool find(const char *target); // reads data from the stream until the target string is found
bool find(const uint8_t *target) { bool find(uint8_t *target) {
return find((const char *)target); return find((char *)target);
} }
// returns true if target string is found, false if timed out (see setTimeout) // returns true if target string is found, false if timed out (see setTimeout)
bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found
bool find(const uint8_t *target, size_t length) { bool find(const uint8_t *target, size_t length) {
return find((const char *)target, length); return find((char *)target, length);
} }
// returns true if target string is found, false if timed out // returns true if target string is found, false if timed out
@ -87,23 +76,19 @@ public:
bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found
bool findUntil(const uint8_t *target, const char *terminator) { bool findUntil(const uint8_t *target, const char *terminator) {
return findUntil((const char *)target, terminator); return findUntil((char *)target, terminator);
} }
bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) { bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {
return findUntil((const char *)target, targetLen, terminate, termLen); return findUntil((char *)target, targetLen, terminate, termLen);
} }
long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); long parseInt(); // returns the first valid (long) integer value from the current position.
// returns the first valid (long) integer value from the current position. // initial characters that are not digits (or the minus sign) are skipped
// lookahead determines how parseInt looks ahead in the stream. // integer is terminated by the first character that is not a digit.
// See LookaheadMode enumeration at the top of the file.
// Lookahead is terminated by the first character that is not a valid part of an integer.
// Once parsing commences, 'ignore' will be skipped in the stream.
float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); float parseFloat(); // float version of parseInt
// float version of parseInt
virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer
virtual size_t readBytes(uint8_t *buffer, size_t length) { virtual size_t readBytes(uint8_t *buffer, size_t length) {
@ -124,15 +109,11 @@ public:
String readStringUntil(char terminator); String readStringUntil(char terminator);
protected: protected:
long parseInt(char ignore) { long parseInt(char skipChar); // as above but the given skipChar is ignored
return parseInt(SKIP_ALL, ignore); // as above but the given skipChar is ignored
} // this allows format characters (typically commas) in values to be ignored
float parseFloat(char ignore) {
return parseFloat(SKIP_ALL, ignore); float parseFloat(char skipChar); // as above but the given skipChar is ignored
}
// These overload exists for compatibility with any class that has derived
// Stream and used parseFloat/Int with a custom ignore character. To keep
// the public API simple, these overload remains protected.
struct MultiTarget { struct MultiTarget {
const char *str; // string you're searching for const char *str; // string you're searching for
@ -145,4 +126,4 @@ protected:
int findMulti(struct MultiTarget *targets, int tCount); int findMulti(struct MultiTarget *targets, int tCount);
}; };
#undef NO_IGNORE_CHAR #endif

View file

@ -4,11 +4,9 @@
#include "freertos/queue.h" #include "freertos/queue.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#if SOC_LEDC_SUPPORTED
static TaskHandle_t _tone_task = NULL; static TaskHandle_t _tone_task = NULL;
static QueueHandle_t _tone_queue = NULL; static QueueHandle_t _tone_queue = NULL;
static int8_t _pin = -1; static int8_t _pin = -1;
static uint8_t _channel = 255;
typedef enum { typedef enum {
TONE_START, TONE_START,
@ -22,12 +20,6 @@ typedef struct {
unsigned long duration; unsigned long duration;
} tone_msg_t; } tone_msg_t;
#ifdef SOC_LEDC_SUPPORT_HS_MODE
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM << 1)
#else
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM)
#endif
static void tone_task(void *) { static void tone_task(void *) {
tone_msg_t tone_msg; tone_msg_t tone_msg;
while (1) { while (1) {
@ -37,13 +29,7 @@ static void tone_task(void *) {
log_d("Task received from queue TONE_START: pin=%d, frequency=%u Hz, duration=%lu ms", tone_msg.pin, tone_msg.frequency, tone_msg.duration); log_d("Task received from queue TONE_START: pin=%d, frequency=%u Hz, duration=%lu ms", tone_msg.pin, tone_msg.frequency, tone_msg.duration);
if (_pin == -1) { if (_pin == -1) {
bool ret = true; if (ledcAttach(tone_msg.pin, tone_msg.frequency, 10) == 0) {
if (_channel == 255) {
ret = ledcAttach(tone_msg.pin, tone_msg.frequency, 10);
} else {
ret = ledcAttachChannel(tone_msg.pin, tone_msg.frequency, 10, _channel);
}
if (!ret) {
log_e("Tone start failed"); log_e("Tone start failed");
break; break;
} }
@ -87,7 +73,7 @@ static int tone_init() {
"toneTask", // Name of the task "toneTask", // Name of the task
3500, // Stack size in words 3500, // Stack size in words
NULL, // Task input parameter NULL, // Task input parameter
10, // Priority of the task must be higher than Arduino task 1, // Priority of the task
&_tone_task // Task handle. &_tone_task // Task handle.
); );
if (_tone_task == NULL) { if (_tone_task == NULL) {
@ -140,13 +126,3 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
return; return;
} }
} }
void setToneChannel(uint8_t channel) {
if (channel >= LEDC_CHANNELS) {
log_e("Channel %u is not available (maximum %u)!", channel, LEDC_CHANNELS);
return;
}
_channel = channel;
}
#endif /* SOC_LEDC_SUPPORTED */

View file

@ -100,7 +100,6 @@ static bool tinyusb_device_suspended = false;
void tud_mount_cb(void) { void tud_mount_cb(void) {
tinyusb_device_mounted = true; tinyusb_device_mounted = true;
arduino_usb_event_data_t p; arduino_usb_event_data_t p;
p.suspend.remote_wakeup_en = 0;
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STARTED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY); arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STARTED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
} }
@ -108,7 +107,6 @@ void tud_mount_cb(void) {
void tud_umount_cb(void) { void tud_umount_cb(void) {
tinyusb_device_mounted = false; tinyusb_device_mounted = false;
arduino_usb_event_data_t p; arduino_usb_event_data_t p;
p.suspend.remote_wakeup_en = 0;
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY); arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
} }
@ -125,7 +123,6 @@ void tud_suspend_cb(bool remote_wakeup_en) {
void tud_resume_cb(void) { void tud_resume_cb(void) {
tinyusb_device_suspended = false; tinyusb_device_suspended = false;
arduino_usb_event_data_t p; arduino_usb_event_data_t p;
p.suspend.remote_wakeup_en = 0;
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_RESUME_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY); arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_RESUME_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
} }

View file

@ -25,29 +25,13 @@ ESP_EVENT_DEFINE_BASE(ARDUINO_USB_CDC_EVENTS);
esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait); esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait);
esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg); esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg);
USBCDC *devices[CFG_TUD_CDC]; #define MAX_USB_CDC_DEVICES 2
USBCDC *devices[MAX_USB_CDC_DEVICES] = {NULL, NULL};
static uint16_t load_cdc_descriptor(uint8_t *dst, uint8_t *itf) { static uint16_t load_cdc_descriptor(uint8_t *dst, uint8_t *itf) {
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC"); uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC");
uint8_t descriptor[TUD_CDC_DESC_LEN] = {// Interface number, string index, EP notification address and size, EP data address (out, in) and size. uint8_t descriptor[TUD_CDC_DESC_LEN] = {// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, CFG_TUD_ENDOINT_SIZE, 0x03, 0x84, CFG_TUD_ENDOINT_SIZE) TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, 64, 0x03, 0x84, 64)
};
*itf += 2;
memcpy(dst, descriptor, TUD_CDC_DESC_LEN);
return TUD_CDC_DESC_LEN;
}
static uint16_t load_cdc_descriptor2(uint8_t *dst, uint8_t *itf) {
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC2");
uint8_t ep_ntfy = tinyusb_get_free_in_endpoint();
TU_VERIFY(ep_ntfy != 0);
uint8_t ep_in = tinyusb_get_free_in_endpoint();
TU_VERIFY(ep_in != 0);
uint8_t ep_out = tinyusb_get_free_out_endpoint();
TU_VERIFY(ep_out != 0);
uint8_t descriptor[TUD_CDC_DESC_LEN] = {
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(*itf, str_index, (uint8_t)(0x80 | ep_ntfy), CFG_TUD_ENDOINT_SIZE, ep_out, (uint8_t)(0x80 | ep_in), CFG_TUD_ENDOINT_SIZE)
}; };
*itf += 2; *itf += 2;
memcpy(dst, descriptor, TUD_CDC_DESC_LEN); memcpy(dst, descriptor, TUD_CDC_DESC_LEN);
@ -56,24 +40,21 @@ static uint16_t load_cdc_descriptor2(uint8_t *dst, uint8_t *itf) {
// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE // Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
//log_v("ITF: %u, DTR: %u, RTS: %u", itf, dtr, rts); if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) {
if (itf < CFG_TUD_CDC && devices[itf] != NULL) {
devices[itf]->_onLineState(dtr, rts); devices[itf]->_onLineState(dtr, rts);
} }
} }
// Invoked when line coding is change via SET_LINE_CODING // Invoked when line coding is change via SET_LINE_CODING
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) { void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) {
//log_v("ITF: %u, BITRATE: %lu, STOP_BITS: %u, PARITY: %u, DATA_BITS: %u", itf, p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits); if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) {
if (itf < CFG_TUD_CDC && devices[itf] != NULL) {
devices[itf]->_onLineCoding(p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits); devices[itf]->_onLineCoding(p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits);
} }
} }
// Invoked when received new data // Invoked when received new data
void tud_cdc_rx_cb(uint8_t itf) { void tud_cdc_rx_cb(uint8_t itf) {
//log_v("ITF: %u", itf); if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) {
if (itf < CFG_TUD_CDC && devices[itf] != NULL) {
devices[itf]->_onRX(); devices[itf]->_onRX();
} }
} }
@ -85,13 +66,13 @@ void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) {
// Invoked when space becomes available in TX buffer // Invoked when space becomes available in TX buffer
void tud_cdc_tx_complete_cb(uint8_t itf) { void tud_cdc_tx_complete_cb(uint8_t itf) {
if (itf < CFG_TUD_CDC && devices[itf] != NULL) { if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) {
devices[itf]->_onTX(); devices[itf]->_onTX();
} }
} }
static void ARDUINO_ISR_ATTR cdc0_write_char(char c) { static void ARDUINO_ISR_ATTR cdc0_write_char(char c) {
if (CFG_TUD_CDC && devices[0] != NULL) { if (devices[0] != NULL) {
tud_cdc_n_write_char(0, c); tud_cdc_n_write_char(0, c);
} }
} }
@ -103,15 +84,9 @@ static void usb_unplugged_cb(void *arg, esp_event_base_t event_base, int32_t eve
USBCDC::USBCDC(uint8_t itfn) USBCDC::USBCDC(uint8_t itfn)
: itf(itfn), bit_rate(0), stop_bits(0), parity(0), data_bits(0), dtr(false), rts(false), connected(false), reboot_enable(true), rx_queue(NULL), tx_lock(NULL), : itf(itfn), bit_rate(0), stop_bits(0), parity(0), data_bits(0), dtr(false), rts(false), connected(false), reboot_enable(true), rx_queue(NULL), tx_lock(NULL),
tx_timeout_ms(250) { tx_timeout_ms(250) {
if (itf < CFG_TUD_CDC) { tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
if (itf == 0) { if (itf < MAX_USB_CDC_DEVICES) {
tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
} else {
tinyusb_enable_interface(USB_INTERFACE_CDC2, TUD_CDC_DESC_LEN, load_cdc_descriptor2);
}
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this); arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this);
} else {
log_e("Maximum of %u CDC devices are supported", CFG_TUD_CDC);
} }
} }
@ -167,9 +142,6 @@ size_t USBCDC::setRxBufferSize(size_t rx_queue_len) {
} }
void USBCDC::begin(unsigned long baud) { void USBCDC::begin(unsigned long baud) {
if (itf >= CFG_TUD_CDC) {
return;
}
if (tx_lock == NULL) { if (tx_lock == NULL) {
tx_lock = xSemaphoreCreateMutex(); tx_lock = xSemaphoreCreateMutex();
} }
@ -181,9 +153,6 @@ void USBCDC::begin(unsigned long baud) {
} }
void USBCDC::end() { void USBCDC::end() {
if (itf >= CFG_TUD_CDC) {
return;
}
connected = false; connected = false;
devices[itf] = NULL; devices[itf] = NULL;
setRxBufferSize(0); setRxBufferSize(0);
@ -329,14 +298,14 @@ bool USBCDC::rebootEnabled(void) {
} }
int USBCDC::available(void) { int USBCDC::available(void) {
if (itf >= CFG_TUD_CDC || rx_queue == NULL) { if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) {
return -1; return -1;
} }
return uxQueueMessagesWaiting(rx_queue); return uxQueueMessagesWaiting(rx_queue);
} }
int USBCDC::peek(void) { int USBCDC::peek(void) {
if (itf >= CFG_TUD_CDC || rx_queue == NULL) { if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) {
return -1; return -1;
} }
uint8_t c; uint8_t c;
@ -347,7 +316,7 @@ int USBCDC::peek(void) {
} }
int USBCDC::read(void) { int USBCDC::read(void) {
if (itf >= CFG_TUD_CDC || rx_queue == NULL) { if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) {
return -1; return -1;
} }
uint8_t c = 0; uint8_t c = 0;
@ -358,7 +327,7 @@ int USBCDC::read(void) {
} }
size_t USBCDC::read(uint8_t *buffer, size_t size) { size_t USBCDC::read(uint8_t *buffer, size_t size) {
if (itf >= CFG_TUD_CDC || rx_queue == NULL) { if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) {
return -1; return -1;
} }
uint8_t c = 0; uint8_t c = 0;
@ -370,7 +339,7 @@ size_t USBCDC::read(uint8_t *buffer, size_t size) {
} }
void USBCDC::flush(void) { void USBCDC::flush(void) {
if (itf >= CFG_TUD_CDC || tx_lock == NULL || !tud_cdc_n_connected(itf)) { if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected(itf)) {
return; return;
} }
if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) { if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) {
@ -381,7 +350,7 @@ void USBCDC::flush(void) {
} }
int USBCDC::availableForWrite(void) { int USBCDC::availableForWrite(void) {
if (itf >= CFG_TUD_CDC || tx_lock == NULL || !tud_cdc_n_connected(itf)) { if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected(itf)) {
return 0; return 0;
} }
if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) { if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) {
@ -393,7 +362,7 @@ int USBCDC::availableForWrite(void) {
} }
size_t USBCDC::write(const uint8_t *buffer, size_t size) { size_t USBCDC::write(const uint8_t *buffer, size_t size) {
if (itf >= CFG_TUD_CDC || tx_lock == NULL || buffer == NULL || size == 0 || !tud_cdc_n_connected(itf)) { if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || buffer == NULL || size == 0 || !tud_cdc_n_connected(itf)) {
return 0; return 0;
} }
if (xPortInIsrContext()) { if (xPortInIsrContext()) {
@ -446,20 +415,16 @@ uint32_t USBCDC::baudRate() {
} }
void USBCDC::setDebugOutput(bool en) { void USBCDC::setDebugOutput(bool en) {
if (itf) {
return;
}
if (en) { if (en) {
uartSetDebug(NULL); uartSetDebug(NULL);
ets_install_putc2((void (*)(char)) & cdc0_write_char); ets_install_putc2((void (*)(char)) & cdc0_write_char);
} else { } else {
ets_install_putc2(NULL); ets_install_putc2(NULL);
} }
ets_install_putc1(NULL); // closes UART log output
} }
USBCDC::operator bool() const { USBCDC::operator bool() const {
if (itf >= CFG_TUD_CDC) { if (itf >= MAX_USB_CDC_DEVICES) {
return false; return false;
} }
return connected; return connected;

View file

@ -24,7 +24,7 @@ extern "C" uint16_t tusb_msc_load_descriptor(uint8_t *dst, uint8_t *itf) {
uint8_t ep_num = tinyusb_get_free_duplex_endpoint(); uint8_t ep_num = tinyusb_get_free_duplex_endpoint();
TU_VERIFY(ep_num != 0); TU_VERIFY(ep_num != 0);
uint8_t descriptor[TUD_MSC_DESC_LEN] = {// Interface number, string index, EP Out & EP In address, EP size uint8_t descriptor[TUD_MSC_DESC_LEN] = {// Interface number, string index, EP Out & EP In address, EP size
TUD_MSC_DESCRIPTOR(*itf, str_index, ep_num, (uint8_t)(0x80 | ep_num), CFG_TUD_ENDOINT_SIZE) TUD_MSC_DESCRIPTOR(*itf, str_index, ep_num, (uint8_t)(0x80 | ep_num), 64)
}; };
*itf += 1; *itf += 1;
memcpy(dst, descriptor, TUD_MSC_DESC_LEN); memcpy(dst, descriptor, TUD_MSC_DESC_LEN);

View file

@ -180,7 +180,7 @@ bool String::changeBuffer(unsigned int maxStrLen) {
if (maxStrLen < sizeof(sso.buff) - 1) { if (maxStrLen < sizeof(sso.buff) - 1) {
if (isSSO() || !buffer()) { if (isSSO() || !buffer()) {
// Already using SSO, nothing to do // Already using SSO, nothing to do
size_t oldLen = len(); uint16_t oldLen = len();
setSSO(true); setSSO(true);
setLen(oldLen); setLen(oldLen);
} else { // if bufptr && !isSSO() } else { // if bufptr && !isSSO()
@ -188,7 +188,7 @@ bool String::changeBuffer(unsigned int maxStrLen) {
char temp[sizeof(sso.buff)]; char temp[sizeof(sso.buff)];
memcpy(temp, buffer(), maxStrLen); memcpy(temp, buffer(), maxStrLen);
free(wbuffer()); free(wbuffer());
size_t oldLen = len(); uint16_t oldLen = len();
setSSO(true); setSSO(true);
memcpy(wbuffer(), temp, maxStrLen); memcpy(wbuffer(), temp, maxStrLen);
setLen(oldLen); setLen(oldLen);
@ -201,7 +201,7 @@ bool String::changeBuffer(unsigned int maxStrLen) {
if (newSize > CAPACITY_MAX) { if (newSize > CAPACITY_MAX) {
return false; return false;
} }
size_t oldLen = len(); uint16_t oldLen = len();
char *newbuffer = (char *)realloc(isSSO() ? nullptr : wbuffer(), newSize); char *newbuffer = (char *)realloc(isSSO() ? nullptr : wbuffer(), newSize);
if (newbuffer) { if (newbuffer) {
size_t oldSize = capacity() + 1; // include NULL. size_t oldSize = capacity() + 1; // include NULL.
@ -226,11 +226,11 @@ bool String::changeBuffer(unsigned int maxStrLen) {
/*********************************************/ /*********************************************/
String &String::copy(const char *cstr, unsigned int length) { String &String::copy(const char *cstr, unsigned int length) {
if (cstr == nullptr || !reserve(length)) { if (!reserve(length)) {
invalidate(); invalidate();
return *this; return *this;
} }
memmove(wbuffer(), cstr, length); memmove(wbuffer(), cstr, length + 1);
setLen(length); setLen(length);
return *this; return *this;
} }
@ -239,18 +239,15 @@ String &String::copy(const char *cstr, unsigned int length) {
void String::move(String &rhs) { void String::move(String &rhs) {
if (buffer()) { if (buffer()) {
if (capacity() >= rhs.len()) { if (capacity() >= rhs.len()) {
// Use case: When 'reserve()' was called and the first memmove(wbuffer(), rhs.buffer(), rhs.length() + 1);
// assignment/append is the return value of a function.
if (rhs.len() && rhs.buffer()) {
memmove(wbuffer(), rhs.buffer(), rhs.length());
}
setLen(rhs.len()); setLen(rhs.len());
rhs.invalidate(); rhs.invalidate();
return; return;
} } else {
if (!isSSO()) { if (!isSSO()) {
free(wbuffer()); free(wbuffer());
setBuffer(nullptr); setBuffer(nullptr);
}
} }
} }
if (rhs.isSSO()) { if (rhs.isSSO()) {
@ -262,7 +259,10 @@ void String::move(String &rhs) {
} }
setCapacity(rhs.capacity()); setCapacity(rhs.capacity());
setLen(rhs.len()); setLen(rhs.len());
rhs.init(); rhs.setSSO(false);
rhs.setCapacity(0);
rhs.setBuffer(nullptr);
rhs.setLen(0);
} }
#endif #endif
@ -270,7 +270,12 @@ String &String::operator=(const String &rhs) {
if (this == &rhs) { if (this == &rhs) {
return *this; return *this;
} }
return copy(rhs.buffer(), rhs.len()); if (rhs.buffer()) {
copy(rhs.buffer(), rhs.len());
} else {
invalidate();
}
return *this;
} }
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
@ -290,8 +295,12 @@ String &String::operator=(StringSumHelper &&rval) {
#endif #endif
String &String::operator=(const char *cstr) { String &String::operator=(const char *cstr) {
const uint32_t length = cstr ? strlen(cstr) : 0u; if (cstr) {
return copy(cstr, length); copy(cstr, strlen(cstr));
} else {
invalidate();
}
return *this;
} }
/*********************************************/ /*********************************************/
@ -302,21 +311,23 @@ bool String::concat(const String &s) {
// Special case if we're concatting ourself (s += s;) since we may end up // Special case if we're concatting ourself (s += s;) since we may end up
// realloc'ing the buffer and moving s.buffer in the method called // realloc'ing the buffer and moving s.buffer in the method called
if (&s == this) { if (&s == this) {
if (s.len() == 0) { unsigned int newlen = 2 * len();
return true;
}
if (!s.buffer()) { if (!s.buffer()) {
return false; return false;
} }
unsigned int newlen = 2 * len(); if (s.len() == 0) {
return true;
}
if (!reserve(newlen)) { if (!reserve(newlen)) {
return false; return false;
} }
memmove(wbuffer() + len(), buffer(), len()); memmove(wbuffer() + len(), buffer(), len());
setLen(newlen); setLen(newlen);
wbuffer()[len()] = 0;
return true; return true;
} else {
return concat(s.buffer(), s.len());
} }
return concat(s.buffer(), s.len());
} }
bool String::concat(const char *cstr, unsigned int length) { bool String::concat(const char *cstr, unsigned int length) {
@ -332,10 +343,10 @@ bool String::concat(const char *cstr, unsigned int length) {
} }
if (cstr >= wbuffer() && cstr < wbuffer() + len()) { if (cstr >= wbuffer() && cstr < wbuffer() + len()) {
// compatible with SSO in ram #6155 (case "x += x.c_str()") // compatible with SSO in ram #6155 (case "x += x.c_str()")
memmove(wbuffer() + len(), cstr, length); memmove(wbuffer() + len(), cstr, length + 1);
} else { } else {
// compatible with source in flash #6367 // compatible with source in flash #6367
memcpy_P(wbuffer() + len(), cstr, length); memcpy_P(wbuffer() + len(), cstr, length + 1);
} }
setLen(newlen); setLen(newlen);
return true; return true;

View file

@ -64,13 +64,6 @@ static void printPkgVersion(void) {
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SYS_4_REG, EFUSE_PKG_VERSION); uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SYS_4_REG, EFUSE_PKG_VERSION);
chip_report_printf("%lu", pkg_ver); chip_report_printf("%lu", pkg_ver);
#elif CONFIG_IDF_TARGET_ESP32P4
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SYS_2_REG, EFUSE_PKG_VERSION);
chip_report_printf("%lu", pkg_ver);
#elif CONFIG_IDF_TARGET_ESP32C5
// ToDo: Update this line when EFUSE_PKG_VERSION is available again for ESP32-C5
uint32_t pkg_ver = 0; //REG_GET_FIELD(EFUSE_RD_MAC_SYS2_REG, EFUSE_PKG_VERSION);
chip_report_printf("%lu", pkg_ver);
#else #else
chip_report_printf("Unknown"); chip_report_printf("Unknown");
#endif #endif
@ -91,16 +84,15 @@ static void printChipInfo(void) {
case CHIP_ESP32C3: chip_report_printf("ESP32-C3\n"); break; case CHIP_ESP32C3: chip_report_printf("ESP32-C3\n"); break;
case CHIP_ESP32C6: chip_report_printf("ESP32-C6\n"); break; case CHIP_ESP32C6: chip_report_printf("ESP32-C6\n"); break;
case CHIP_ESP32H2: chip_report_printf("ESP32-H2\n"); break; case CHIP_ESP32H2: chip_report_printf("ESP32-H2\n"); break;
case CHIP_ESP32P4: chip_report_printf("ESP32-P4\n"); break; default: chip_report_printf("Unknown %d\n", info.model); break;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
case CHIP_ESP32C5: chip_report_printf("ESP32-C5\n"); break;
case CHIP_ESP32C61: chip_report_printf("ESP32-C61\n"); break;
case CHIP_ESP32H21: chip_report_printf("ESP32-H21\n"); break;
#endif
default: chip_report_printf("Unknown %d\n", info.model); break;
} }
printPkgVersion(); printPkgVersion();
chip_report_printf(" Revision : %.2f\n", (float)(info.revision) / 100.0); chip_report_printf(" Revision : ");
if (info.revision > 0xFF) {
chip_report_printf("%d.%d\n", info.revision >> 8, info.revision & 0xFF);
} else {
chip_report_printf("%d\n", info.revision);
}
chip_report_printf(" Cores : %d\n", info.cores); chip_report_printf(" Cores : %d\n", info.cores);
rtc_cpu_freq_config_t conf; rtc_cpu_freq_config_t conf;
rtc_clk_cpu_freq_get_config(&conf); rtc_clk_cpu_freq_get_config(&conf);
@ -118,8 +110,6 @@ static void printChipInfo(void) {
static void printFlashInfo(void) { static void printFlashInfo(void) {
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
#define ESP_FLASH_IMAGE_BASE 0x1000 #define ESP_FLASH_IMAGE_BASE 0x1000
#elif CONFIG_IDF_TARGET_ESP32P4
#define ESP_FLASH_IMAGE_BASE 0x2000
#else #else
#define ESP_FLASH_IMAGE_BASE 0x0000 #define ESP_FLASH_IMAGE_BASE 0x0000
#endif #endif

View file

@ -75,7 +75,7 @@ static bool adcDetachBus(void *pin) {
if (err != ESP_OK) { if (err != ESP_OK) {
return false; return false;
} }
#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) #elif !defined(CONFIG_IDF_TARGET_ESP32H2)
err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle); err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle);
if (err != ESP_OK) { if (err != ESP_OK) {
return false; return false;
@ -127,7 +127,7 @@ esp_err_t __analogChannelConfig(adc_bitwidth_t width, adc_attenuation_t atten, i
log_e("adc_cali_create_scheme_curve_fitting failed with error: %d", err); log_e("adc_cali_create_scheme_curve_fitting failed with error: %d", err);
return err; return err;
} }
#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED #elif !defined(CONFIG_IDF_TARGET_ESP32H2) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
log_d("Deleting ADC_UNIT_%d line cali handle", adc_unit); log_d("Deleting ADC_UNIT_%d line cali handle", adc_unit);
err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle); err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle);
if (err != ESP_OK) { if (err != ESP_OK) {
@ -310,7 +310,7 @@ uint32_t __analogReadMilliVolts(uint8_t pin) {
.bitwidth = __analogWidth, .bitwidth = __analogWidth,
}; };
err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_handle[adc_unit].adc_cali_handle); err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_handle[adc_unit].adc_cali_handle);
#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED #elif !defined(CONFIG_IDF_TARGET_ESP32H2) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
adc_cali_line_fitting_config_t cali_config = { adc_cali_line_fitting_config_t cali_config = {
.unit_id = adc_unit, .unit_id = adc_unit,
.bitwidth = __analogWidth, .bitwidth = __analogWidth,
@ -379,7 +379,7 @@ static bool adcContinuousDetachBus(void *adc_unit_number) {
if (err != ESP_OK) { if (err != ESP_OK) {
return false; return false;
} }
#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) #elif !defined(CONFIG_IDF_TARGET_ESP32H2)
err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle); err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle);
if (err != ESP_OK) { if (err != ESP_OK) {
return false; return false;
@ -552,7 +552,7 @@ bool analogContinuous(const uint8_t pins[], size_t pins_count, uint32_t conversi
.bitwidth = __adcContinuousWidth, .bitwidth = __adcContinuousWidth,
}; };
err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_handle[adc_unit].adc_cali_handle); err = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_handle[adc_unit].adc_cali_handle);
#elif (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED #elif !defined(CONFIG_IDF_TARGET_ESP32H2) //ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
adc_cali_line_fitting_config_t cali_config = { adc_cali_line_fitting_config_t cali_config = {
.unit_id = adc_unit, .unit_id = adc_unit,
.bitwidth = __adcContinuousWidth, .bitwidth = __adcContinuousWidth,

View file

@ -15,7 +15,7 @@
#include "esp32-hal-bt.h" #include "esp32-hal-bt.h"
#if SOC_BT_SUPPORTED #if SOC_BT_SUPPORTED
#if (defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)) && __has_include("esp_bt.h") #ifdef CONFIG_BT_ENABLED
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
bool btInUse() { bool btInUse() {
@ -116,7 +116,7 @@ bool btStop() {
return false; return false;
} }
#else // !__has_include("esp_bt.h") || !(defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)) #else // CONFIG_BT_ENABLED
bool btStarted() { bool btStarted() {
return false; return false;
} }
@ -129,6 +129,6 @@ bool btStop() {
return false; return false;
} }
#endif /* !__has_include("esp_bt.h") || !(defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)) */ #endif /* CONFIG_BT_ENABLED */
#endif /* SOC_BT_SUPPORTED */ #endif /* SOC_BT_SUPPORTED */

View file

@ -19,27 +19,24 @@
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_log.h" #include "esp_log.h"
#include "soc/rtc.h" #include "soc/rtc.h"
#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) \ #if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
&& !defined(CONFIG_IDF_TARGET_ESP32C5)
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "soc/syscon_reg.h" #include "soc/apb_ctrl_reg.h"
#endif #endif
#include "soc/efuse_reg.h" #include "soc/efuse_reg.h"
#include "esp32-hal.h" #include "esp32-hal.h"
#include "esp32-hal-cpu.h" #include "esp32-hal-cpu.h"
#include "hal/timer_ll.h"
#include "esp_private/systimer.h"
#include "esp_system.h" #include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+ #ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "xtensa_timer.h" #include "freertos/xtensa_timer.h"
#include "esp32/rom/rtc.h" #include "esp32/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2 #elif CONFIG_IDF_TARGET_ESP32S2
#include "xtensa_timer.h" #include "freertos/xtensa_timer.h"
#include "esp32s2/rom/rtc.h" #include "esp32s2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
#include "xtensa_timer.h" #include "freertos/xtensa_timer.h"
#include "esp32s3/rom/rtc.h" #include "esp32s3/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C2 #elif CONFIG_IDF_TARGET_ESP32C2
#include "esp32c2/rom/rtc.h" #include "esp32c2/rom/rtc.h"
@ -49,10 +46,6 @@
#include "esp32c6/rom/rtc.h" #include "esp32c6/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/rtc.h" #include "esp32h2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/rtc.h"
#else #else
#error Target CONFIG_IDF_TARGET is not supported #error Target CONFIG_IDF_TARGET is not supported
#endif #endif
@ -168,25 +161,23 @@ bool removeApbChangeCallback(void *arg, apb_change_cb_t cb) {
} }
static uint32_t calculateApb(rtc_cpu_freq_config_t *conf) { static uint32_t calculateApb(rtc_cpu_freq_config_t *conf) {
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
return APB_CLK_FREQ;
#else
if (conf->freq_mhz >= 80) { if (conf->freq_mhz >= 80) {
return 80 * MHZ; return 80 * MHZ;
} }
return (conf->source_freq_mhz * MHZ) / conf->div; return (conf->source_freq_mhz * MHZ) / conf->div;
#else
return APB_CLK_FREQ;
#endif #endif
} }
#if defined(CONFIG_IDF_TARGET_ESP32) && !defined(LACT_MODULE) && !defined(LACT_TICKS_PER_US)
void esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us); //private in IDF void esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us); //private in IDF
#endif
bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
rtc_cpu_freq_config_t conf, cconf; rtc_cpu_freq_config_t conf, cconf;
uint32_t capb, apb; uint32_t capb, apb;
//Get XTAL Frequency and calculate min CPU MHz //Get XTAL Frequency and calculate min CPU MHz
#if (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(CONFIG_IDF_TARGET_ESP32C5)) #ifndef CONFIG_IDF_TARGET_ESP32H2
rtc_xtal_freq_t xtal = rtc_clk_xtal_freq_get(); rtc_xtal_freq_t xtal = rtc_clk_xtal_freq_get();
#endif #endif
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
@ -202,7 +193,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
} }
} }
#endif #endif
#if (!defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(CONFIG_IDF_TARGET_ESP32C5)) #ifndef CONFIG_IDF_TARGET_ESP32H2
if (cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 120 && cpu_freq_mhz != 80) { if (cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 120 && cpu_freq_mhz != 80) {
if (xtal >= RTC_XTAL_FREQ_40M) { if (xtal >= RTC_XTAL_FREQ_40M) {
log_e("Bad frequency: %u MHz! Options are: 240, 160, 120, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal / 2, xtal / 4); log_e("Bad frequency: %u MHz! Options are: 240, 160, 120, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal / 2, xtal / 4);
@ -244,7 +235,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
} }
//Make the frequency change //Make the frequency change
rtc_clk_cpu_freq_set_config_fast(&conf); rtc_clk_cpu_freq_set_config_fast(&conf);
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) #if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
if (capb != apb) { if (capb != apb) {
//Update REF_TICK (uncomment if REF_TICK is different than 1MHz) //Update REF_TICK (uncomment if REF_TICK is different than 1MHz)
//if(conf.freq_mhz < 80){ //if(conf.freq_mhz < 80){
@ -253,18 +244,15 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
//Update APB Freq REG //Update APB Freq REG
rtc_clk_apb_freq_update(apb); rtc_clk_apb_freq_update(apb);
//Update esp_timer divisor //Update esp_timer divisor
#if CONFIG_IDF_TARGET_ESP32
#if defined(LACT_MODULE) && defined(LACT_TICKS_PER_US)
timer_ll_set_lact_clock_prescale(TIMER_LL_GET_HW(LACT_MODULE), apb / MHZ / LACT_TICKS_PER_US);
#else
esp_timer_impl_update_apb_freq(apb / MHZ); esp_timer_impl_update_apb_freq(apb / MHZ);
#endif
#endif
} }
#endif #endif
//Update FreeRTOS Tick Divisor //Update FreeRTOS Tick Divisor
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #elif CONFIG_IDF_TARGET_ESP32S3
#else
uint32_t fcpu = (conf.freq_mhz >= 80) ? (conf.freq_mhz * MHZ) : (apb); uint32_t fcpu = (conf.freq_mhz >= 80) ? (conf.freq_mhz * MHZ) : (apb);
_xt_tick_divisor = fcpu / XT_TICK_PER_SEC; _xt_tick_divisor = fcpu / XT_TICK_PER_SEC;
#endif #endif
@ -272,21 +260,16 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
if (apb_change_callbacks) { if (apb_change_callbacks) {
triggerApbChangeCallback(APB_AFTER_CHANGE, capb, apb); triggerApbChangeCallback(APB_AFTER_CHANGE, capb, apb);
} }
#if defined(SOC_CLK_APLL_SUPPORTED) && !defined(CONFIG_IDF_TARGET_ESP32P4) // APLL not yet supported in ESP32-P4 #ifdef SOC_CLK_APLL_SUPPORTED
log_d( log_d(
"%s: %u / %u = %u Mhz, APB: %u Hz", "%s: %u / %u = %u Mhz, APB: %u Hz",
(conf.source == SOC_CPU_CLK_SRC_PLL) ? "PLL" : ((conf.source == SOC_CPU_CLK_SRC_APLL) ? "APLL" : ((conf.source == SOC_CPU_CLK_SRC_XTAL) ? "XTAL" : "8M")), (conf.source == RTC_CPU_FREQ_SRC_PLL) ? "PLL"
conf.source_freq_mhz, conf.div, conf.freq_mhz, apb : ((conf.source == RTC_CPU_FREQ_SRC_APLL) ? "APLL" : ((conf.source == RTC_CPU_FREQ_SRC_XTAL) ? "XTAL" : "8M")),
);
#elif defined(CONFIG_IDF_TARGET_ESP32C5)
log_d(
"%s: %u / %u = %u Mhz, APB: %u Hz",
(conf.source == SOC_CPU_CLK_SRC_PLL_F240M || conf.source == SOC_CPU_CLK_SRC_PLL_F160M) ? "PLL" : ((conf.source == SOC_CPU_CLK_SRC_XTAL) ? "XTAL" : "8M"),
conf.source_freq_mhz, conf.div, conf.freq_mhz, apb conf.source_freq_mhz, conf.div, conf.freq_mhz, apb
); );
#else #else
log_d( log_d(
"%s: %u / %u = %u Mhz, APB: %u Hz", (conf.source == SOC_CPU_CLK_SRC_PLL) ? "PLL" : ((conf.source == SOC_CPU_CLK_SRC_XTAL) ? "XTAL" : "17.5M"), "%s: %u / %u = %u Mhz, APB: %u Hz", (conf.source == RTC_CPU_FREQ_SRC_PLL) ? "PLL" : ((conf.source == RTC_CPU_FREQ_SRC_XTAL) ? "XTAL" : "17.5M"),
conf.source_freq_mhz, conf.div, conf.freq_mhz, apb conf.source_freq_mhz, conf.div, conf.freq_mhz, apb
); );
#endif #endif

View file

@ -173,7 +173,7 @@ extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val) {
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) { if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) {
gpio_set_level((gpio_num_t)pin, val); gpio_set_level((gpio_num_t)pin, val);
} else { } else {
log_e("IO %i is not set as GPIO. Execute digitalMode(%i, OUTPUT) first.", pin, pin); log_e("IO %i is not set as GPIO.", pin);
} }
} }
@ -182,12 +182,14 @@ extern int ARDUINO_ISR_ATTR __digitalRead(uint8_t pin) {
if (pin == RGB_BUILTIN) { if (pin == RGB_BUILTIN) {
return RGB_BUILTIN_storage; return RGB_BUILTIN_storage;
} }
#endif // RGB_BUILTIN #endif
// This work when the pin is set as GPIO and in INPUT mode. For all other pin functions, it may return inconsistent response
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) == NULL) { if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) {
log_w("IO %i is not set as GPIO. digitalRead() may return an inconsistent value.", pin); return gpio_get_level((gpio_num_t)pin);
} else {
log_e("IO %i is not set as GPIO.", pin);
return 0;
} }
return gpio_get_level((gpio_num_t)pin);
} }
static void ARDUINO_ISR_ATTR __onPinInterrupt(void *arg) { static void ARDUINO_ISR_ATTR __onPinInterrupt(void *arg) {

View file

@ -24,9 +24,9 @@
extern "C" { extern "C" {
#endif #endif
#include "pins_arduino.h"
#include "esp32-hal.h" #include "esp32-hal.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "pins_arduino.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) #if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)

View file

@ -1,452 +0,0 @@
// Copyright 2015-2025 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "esp32-hal-i2c.h"
#if SOC_I2C_SUPPORTED
#include "esp_idf_version.h"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
#include "esp32-hal.h"
#if !CONFIG_DISABLE_HAL_LOCKS
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#endif
#include "esp_attr.h"
#include "esp_system.h"
#include "soc/soc_caps.h"
#include "driver/i2c_master.h"
#include "esp32-hal-periman.h"
typedef volatile struct {
bool initialized;
uint32_t frequency;
#if !CONFIG_DISABLE_HAL_LOCKS
SemaphoreHandle_t lock;
#endif
int8_t scl;
int8_t sda;
i2c_master_bus_handle_t bus_handle;
i2c_master_dev_handle_t dev_handles[128];
} i2c_bus_t;
static i2c_bus_t bus[SOC_I2C_NUM];
static bool i2cDetachBus(void *bus_i2c_num) {
uint8_t i2c_num = (int)bus_i2c_num - 1;
if (!bus[i2c_num].initialized) {
return true;
}
esp_err_t err = i2cDeinit(i2c_num);
if (err != ESP_OK) {
log_e("i2cDeinit failed with error: %d", err);
return false;
}
return true;
}
void *i2cBusHandle(uint8_t i2c_num) {
if (i2c_num >= SOC_I2C_NUM) {
return NULL;
}
return bus[i2c_num].bus_handle;
}
bool i2cIsInit(uint8_t i2c_num) {
if (i2c_num >= SOC_I2C_NUM) {
return false;
}
return bus[i2c_num].initialized;
}
esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
esp_err_t ret = ESP_OK;
if (i2c_num >= SOC_I2C_NUM) {
return ESP_ERR_INVALID_ARG;
}
#if !CONFIG_DISABLE_HAL_LOCKS
if (bus[i2c_num].lock == NULL) {
bus[i2c_num].lock = xSemaphoreCreateMutex();
if (bus[i2c_num].lock == NULL) {
log_e("xSemaphoreCreateMutex failed");
return ESP_ERR_NO_MEM;
}
}
//acquire lock
if (xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
log_e("could not acquire lock");
return ESP_FAIL;
}
#endif
if (bus[i2c_num].initialized) {
log_e("bus is already initialized");
ret = ESP_FAIL;
goto init_fail;
}
if (!frequency) {
frequency = 100000UL;
} else if (frequency > 1000000UL) {
frequency = 1000000UL;
}
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SDA, i2cDetachBus);
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SCL, i2cDetachBus);
if (!perimanClearPinBus(sda) || !perimanClearPinBus(scl)) {
ret = ESP_FAIL;
goto init_fail;
}
log_i("Initializing I2C Master: num=%u sda=%d scl=%d freq=%lu", i2c_num, sda, scl, frequency);
i2c_master_bus_handle_t bus_handle = NULL;
i2c_master_bus_config_t bus_config;
memset(&bus_config, 0, sizeof(i2c_master_bus_config_t));
bus_config.i2c_port = (i2c_port_num_t)i2c_num;
bus_config.sda_io_num = (gpio_num_t)sda;
bus_config.scl_io_num = (gpio_num_t)scl;
#if SOC_LP_I2C_SUPPORTED
if (i2c_num >= SOC_HP_I2C_NUM) {
bus_config.lp_source_clk = LP_I2C_SCLK_DEFAULT;
} else
#endif
{
bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
}
bus_config.glitch_ignore_cnt = 7;
bus_config.intr_priority = 0; // auto
bus_config.trans_queue_depth = 0; // only valid in asynchronous transaction, which Arduino does not use
bus_config.flags.enable_internal_pullup = 1;
#if SOC_I2C_SUPPORT_SLEEP_RETENTION
bus_config.flags.allow_pd = 1; // backup/restore the I2C registers before/after entering/exist sleep mode
#endif
ret = i2c_new_master_bus(&bus_config, &bus_handle);
if (ret != ESP_OK) {
log_e("i2c_new_master_bus failed: [%d] %s", ret, esp_err_to_name(ret));
} else {
bus[i2c_num].initialized = true;
bus[i2c_num].frequency = frequency;
bus[i2c_num].scl = scl;
bus[i2c_num].sda = sda;
bus[i2c_num].bus_handle = bus_handle;
for (uint8_t i = 0; i < 128; i++) {
bus[i2c_num].dev_handles[i] = NULL;
}
if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER_SDA, (void *)(i2c_num + 1), i2c_num, -1)
|| !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER_SCL, (void *)(i2c_num + 1), i2c_num, -1)) {
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock so that i2cDetachBus can execute i2cDeinit
xSemaphoreGive(bus[i2c_num].lock);
#endif
i2cDetachBus((void *)(i2c_num + 1));
return ESP_FAIL;
}
}
init_fail:
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(bus[i2c_num].lock);
#endif
return ret;
}
esp_err_t i2cDeinit(uint8_t i2c_num) {
esp_err_t err = ESP_FAIL;
if (i2c_num >= SOC_I2C_NUM) {
return ESP_ERR_INVALID_ARG;
}
#if !CONFIG_DISABLE_HAL_LOCKS
//acquire lock
if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
log_e("could not acquire lock");
return err;
}
#endif
if (!bus[i2c_num].initialized) {
log_e("bus is not initialized");
} else {
// remove devices from the bus
for (uint8_t i = 0; i < 128; i++) {
if (bus[i2c_num].dev_handles[i] != NULL) {
err = i2c_master_bus_rm_device(bus[i2c_num].dev_handles[i]);
bus[i2c_num].dev_handles[i] = NULL;
if (err != ESP_OK) {
log_e("i2c_master_bus_rm_device failed: [%d] %s", err, esp_err_to_name(err));
}
}
}
err = i2c_del_master_bus(bus[i2c_num].bus_handle);
if (err != ESP_OK) {
log_e("i2c_del_master_bus failed: [%d] %s", err, esp_err_to_name(err));
} else {
bus[i2c_num].initialized = false;
perimanClearPinBus(bus[i2c_num].scl);
perimanClearPinBus(bus[i2c_num].sda);
bus[i2c_num].scl = -1;
bus[i2c_num].sda = -1;
bus[i2c_num].bus_handle = NULL;
}
}
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(bus[i2c_num].lock);
#endif
return err;
}
static esp_err_t i2cAddDeviceIfNeeded(uint8_t i2c_num, uint16_t address) {
esp_err_t ret = ESP_OK;
if (bus[i2c_num].dev_handles[address] == NULL) {
i2c_master_dev_handle_t dev_handle = NULL;
i2c_device_config_t dev_config;
memset(&dev_config, 0, sizeof(i2c_device_config_t));
dev_config.dev_addr_length = I2C_ADDR_BIT_LEN_7; // Arduino supports only 7bit addresses
dev_config.device_address = address;
dev_config.scl_speed_hz = bus[i2c_num].frequency;
dev_config.scl_wait_us = 0;
dev_config.flags.disable_ack_check = 0;
ret = i2c_master_bus_add_device(bus[i2c_num].bus_handle, &dev_config, &dev_handle);
if (ret != ESP_OK) {
log_e("i2c_master_bus_add_device failed: [%d] %s", ret, esp_err_to_name(ret));
} else {
bus[i2c_num].dev_handles[address] = dev_handle;
log_v("added device: bus=%u addr=0x%x handle=0x%08x", i2c_num, address, dev_handle);
}
}
return ret;
}
esp_err_t i2cWrite(uint8_t i2c_num, uint16_t address, const uint8_t *buff, size_t size, uint32_t timeOutMillis) {
esp_err_t ret = ESP_FAIL;
// i2c_cmd_handle_t cmd = NULL;
if (i2c_num >= SOC_I2C_NUM) {
return ESP_ERR_INVALID_ARG;
}
if (address >= 128) {
log_e("Only 7bit I2C addresses are supported");
return ESP_ERR_INVALID_ARG;
}
#if !CONFIG_DISABLE_HAL_LOCKS
//acquire lock
if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
log_e("could not acquire lock");
return ret;
}
#endif
if (!bus[i2c_num].initialized) {
log_e("bus is not initialized");
goto end;
}
if (size == 0) {
// Probe device
ret = i2c_master_probe(bus[i2c_num].bus_handle, address, timeOutMillis);
if (ret != ESP_OK) {
log_v("i2c_master_probe failed: [%d] %s", ret, esp_err_to_name(ret));
}
} else {
// writing data to device
ret = i2cAddDeviceIfNeeded(i2c_num, address);
if (ret != ESP_OK) {
goto end;
}
log_v("i2c_master_transmit: bus=%u addr=0x%x handle=0x%08x size=%u", i2c_num, address, bus[i2c_num].dev_handles[address], size);
ret = i2c_master_transmit(bus[i2c_num].dev_handles[address], buff, size, timeOutMillis);
if (ret != ESP_OK) {
log_e("i2c_master_transmit failed: [%d] %s", ret, esp_err_to_name(ret));
goto end;
}
// wait for transactions to finish (is it needed with sync transactions?)
// ret = i2c_master_bus_wait_all_done(bus[i2c_num].bus_handle, timeOutMillis);
// if (ret != ESP_OK) {
// log_e("i2c_master_bus_wait_all_done failed: [%d] %s", ret, esp_err_to_name(ret));
// goto end;
// }
}
end:
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(bus[i2c_num].lock);
#endif
return ret;
}
esp_err_t i2cRead(uint8_t i2c_num, uint16_t address, uint8_t *buff, size_t size, uint32_t timeOutMillis, size_t *readCount) {
esp_err_t ret = ESP_FAIL;
*readCount = 0;
if (i2c_num >= SOC_I2C_NUM) {
return ESP_ERR_INVALID_ARG;
}
#if !CONFIG_DISABLE_HAL_LOCKS
//acquire lock
if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
log_e("could not acquire lock");
return ret;
}
#endif
if (!bus[i2c_num].initialized) {
log_e("bus is not initialized");
goto end;
}
ret = i2cAddDeviceIfNeeded(i2c_num, address);
if (ret != ESP_OK) {
goto end;
}
log_v("i2c_master_receive: bus=%u addr=0x%x handle=0x%08x size=%u", i2c_num, address, bus[i2c_num].dev_handles[address], size);
ret = i2c_master_receive(bus[i2c_num].dev_handles[address], buff, size, timeOutMillis);
if (ret != ESP_OK) {
log_e("i2c_master_receive failed: [%d] %s", ret, esp_err_to_name(ret));
goto end;
}
// wait for transactions to finish (is it needed with sync transactions?)
// ret = i2c_master_bus_wait_all_done(bus[i2c_num].bus_handle, timeOutMillis);
// if (ret != ESP_OK) {
// log_e("i2c_master_bus_wait_all_done failed: [%d] %s", ret, esp_err_to_name(ret));
// goto end;
// }
*readCount = size;
end:
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(bus[i2c_num].lock);
#endif
return ret;
}
esp_err_t i2cWriteReadNonStop(
uint8_t i2c_num, uint16_t address, const uint8_t *wbuff, size_t wsize, uint8_t *rbuff, size_t rsize, uint32_t timeOutMillis, size_t *readCount
) {
esp_err_t ret = ESP_FAIL;
*readCount = 0;
if (i2c_num >= SOC_I2C_NUM) {
return ESP_ERR_INVALID_ARG;
}
#if !CONFIG_DISABLE_HAL_LOCKS
//acquire lock
if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
log_e("could not acquire lock");
return ret;
}
#endif
if (!bus[i2c_num].initialized) {
log_e("bus is not initialized");
goto end;
}
ret = i2cAddDeviceIfNeeded(i2c_num, address);
if (ret != ESP_OK) {
goto end;
}
log_v("i2c_master_transmit_receive: bus=%u addr=0x%x handle=0x%08x write=%u read=%u", i2c_num, address, bus[i2c_num].dev_handles[address], wsize, rsize);
ret = i2c_master_transmit_receive(bus[i2c_num].dev_handles[address], wbuff, wsize, rbuff, rsize, timeOutMillis);
if (ret != ESP_OK) {
log_e("i2c_master_transmit_receive failed: [%d] %s", ret, esp_err_to_name(ret));
goto end;
}
// wait for transactions to finish (is it needed with sync transactions?)
// ret = i2c_master_bus_wait_all_done(bus[i2c_num].bus_handle, timeOutMillis);
// if (ret != ESP_OK) {
// log_e("i2c_master_bus_wait_all_done failed: [%d] %s", ret, esp_err_to_name(ret));
// goto end;
// }
*readCount = rsize;
end:
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(bus[i2c_num].lock);
#endif
return ret;
}
esp_err_t i2cSetClock(uint8_t i2c_num, uint32_t frequency) {
esp_err_t ret = ESP_FAIL;
if (i2c_num >= SOC_I2C_NUM) {
return ESP_ERR_INVALID_ARG;
}
#if !CONFIG_DISABLE_HAL_LOCKS
//acquire lock
if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
log_e("could not acquire lock");
return ret;
}
#endif
if (!bus[i2c_num].initialized) {
log_e("bus is not initialized");
goto end;
}
if (bus[i2c_num].frequency == frequency) {
ret = ESP_OK;
goto end;
}
if (!frequency) {
frequency = 100000UL;
} else if (frequency > 1000000UL) {
frequency = 1000000UL;
}
bus[i2c_num].frequency = frequency;
// loop through devices, remove them and then re-add them with the new frequency
for (uint8_t i = 0; i < 128; i++) {
if (bus[i2c_num].dev_handles[i] != NULL) {
ret = i2c_master_bus_rm_device(bus[i2c_num].dev_handles[i]);
if (ret != ESP_OK) {
log_e("i2c_master_bus_rm_device failed: [%d] %s", ret, esp_err_to_name(ret));
goto end;
} else {
bus[i2c_num].dev_handles[i] = NULL;
ret = i2cAddDeviceIfNeeded(i2c_num, i);
if (ret != ESP_OK) {
goto end;
}
}
}
}
end:
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(bus[i2c_num].lock);
#endif
return ret;
}
esp_err_t i2cGetClock(uint8_t i2c_num, uint32_t *frequency) {
if (i2c_num >= SOC_I2C_NUM) {
return ESP_ERR_INVALID_ARG;
}
if (!bus[i2c_num].initialized) {
log_e("bus is not initialized");
return ESP_FAIL;
}
*frequency = bus[i2c_num].frequency;
return ESP_OK;
}
#endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0) */
#endif /* SOC_I2C_SUPPORTED */

View file

@ -41,43 +41,21 @@
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "soc/i2c_reg.h" #include "soc/i2c_reg.h"
#include "soc/i2c_struct.h" #include "soc/i2c_struct.h"
#include "soc/periph_defs.h"
#include "hal/i2c_ll.h" #include "hal/i2c_ll.h"
#include "hal/i2c_types.h"
#ifndef CONFIG_IDF_TARGET_ESP32C5
#include "hal/clk_gate_ll.h" #include "hal/clk_gate_ll.h"
#endif
#include "esp32-hal-log.h" #include "esp32-hal-log.h"
#include "esp32-hal-i2c-slave.h" #include "esp32-hal-i2c-slave.h"
#include "esp32-hal-periman.h" #include "esp32-hal-periman.h"
#include "esp_private/periph_ctrl.h"
#if SOC_PERIPH_CLK_CTRL_SHARED
#define I2C_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define I2C_CLOCK_SRC_ATOMIC()
#endif
#if !SOC_RCC_IS_INDEPENDENT
#define I2C_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define I2C_RCC_ATOMIC()
#endif
#define I2C_SLAVE_USE_RX_QUEUE 0 // 1: Queue, 0: RingBuffer #define I2C_SLAVE_USE_RX_QUEUE 0 // 1: Queue, 0: RingBuffer
#ifdef CONFIG_IDF_TARGET_ESP32P4 #if SOC_I2C_NUM > 1
#define I2C_SCL_IDX(p) ((p == 0) ? I2C0_SCL_PAD_OUT_IDX : ((p == 1) ? I2C1_SCL_PAD_OUT_IDX : 0))
#define I2C_SDA_IDX(p) ((p == 0) ? I2C0_SDA_PAD_OUT_IDX : ((p == 1) ? I2C1_SDA_PAD_OUT_IDX : 0))
#else
#if SOC_HP_I2C_NUM > 1
#define I2C_SCL_IDX(p) ((p == 0) ? I2CEXT0_SCL_OUT_IDX : ((p == 1) ? I2CEXT1_SCL_OUT_IDX : 0)) #define I2C_SCL_IDX(p) ((p == 0) ? I2CEXT0_SCL_OUT_IDX : ((p == 1) ? I2CEXT1_SCL_OUT_IDX : 0))
#define I2C_SDA_IDX(p) ((p == 0) ? I2CEXT0_SDA_OUT_IDX : ((p == 1) ? I2CEXT1_SDA_OUT_IDX : 0)) #define I2C_SDA_IDX(p) ((p == 0) ? I2CEXT0_SDA_OUT_IDX : ((p == 1) ? I2CEXT1_SDA_OUT_IDX : 0))
#else #else
#define I2C_SCL_IDX(p) I2CEXT0_SCL_OUT_IDX #define I2C_SCL_IDX(p) I2CEXT0_SCL_OUT_IDX
#define I2C_SDA_IDX(p) I2CEXT0_SDA_OUT_IDX #define I2C_SDA_IDX(p) I2CEXT0_SDA_OUT_IDX
#endif #endif
#endif // ifdef CONFIG_IDF_TARGET_ESP32P4
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
#define I2C_TXFIFO_WM_INT_ENA I2C_TXFIFO_EMPTY_INT_ENA #define I2C_TXFIFO_WM_INT_ENA I2C_TXFIFO_EMPTY_INT_ENA
@ -121,14 +99,14 @@ typedef union {
uint32_t val; uint32_t val;
} i2c_slave_queue_event_t; } i2c_slave_queue_event_t;
static i2c_slave_struct_t _i2c_bus_array[SOC_HP_I2C_NUM] = { static i2c_slave_struct_t _i2c_bus_array[SOC_I2C_NUM] = {
{&I2C0, 0, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 {&I2C0, 0, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
, ,
NULL NULL
#endif #endif
}, },
#if SOC_HP_I2C_NUM > 1 #if SOC_I2C_NUM > 1
{&I2C1, 1, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 {&I2C1, 1, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
, ,
@ -195,19 +173,19 @@ static inline void i2c_ll_stretch_clr(i2c_dev_t *hw) {
} }
static inline bool i2c_ll_slave_addressed(i2c_dev_t *hw) { static inline bool i2c_ll_slave_addressed(i2c_dev_t *hw) {
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
return hw->status_reg.slave_addressed;
#else
return hw->sr.slave_addressed; return hw->sr.slave_addressed;
#else
return hw->status_reg.slave_addressed;
#endif #endif
} }
static inline bool i2c_ll_slave_rw(i2c_dev_t *hw) //not exposed by hal_ll static inline bool i2c_ll_slave_rw(i2c_dev_t *hw) //not exposed by hal_ll
{ {
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
return hw->status_reg.slave_rw;
#else
return hw->sr.slave_rw; return hw->sr.slave_rw;
#else
return hw->status_reg.slave_rw;
#endif #endif
} }
@ -232,7 +210,7 @@ static bool i2cSlaveDetachBus(void *bus_i2c_num);
//===================================================================================================================== //=====================================================================================================================
esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void *arg) { esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void *arg) {
if (num >= SOC_HP_I2C_NUM) { if (num >= SOC_I2C_NUM) {
log_e("Invalid port num: %u", num); log_e("Invalid port num: %u", num);
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
@ -246,7 +224,7 @@ esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_ca
} }
esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len) { esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len) {
if (num >= SOC_HP_I2C_NUM) { if (num >= SOC_I2C_NUM) {
log_e("Invalid port num: %u", num); log_e("Invalid port num: %u", num);
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
@ -328,29 +306,17 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t
frequency = 100000L; frequency = 100000L;
} }
frequency = (frequency * 5) / 4; frequency = (frequency * 5) / 4;
#if !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(CONFIG_IDF_TARGET_ESP32C5)
if (i2c->num == 0) { if (i2c->num == 0) {
periph_ll_enable_clk_clear_rst(PERIPH_I2C0_MODULE); periph_ll_enable_clk_clear_rst(PERIPH_I2C0_MODULE);
#if SOC_HP_I2C_NUM > 1 #if SOC_I2C_NUM > 1
} else { } else {
periph_ll_enable_clk_clear_rst(PERIPH_I2C1_MODULE); periph_ll_enable_clk_clear_rst(PERIPH_I2C1_MODULE);
#endif #endif
} }
#endif // !defined(CONFIG_IDF_TARGET_ESP32P4)
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)) || (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0)) \
|| (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 3) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0))
i2c_ll_set_mode(i2c->dev, I2C_BUS_MODE_SLAVE);
i2c_ll_enable_pins_open_drain(i2c->dev, true);
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
i2c_ll_enable_fifo_mode(i2c->dev, true);
#else
i2c_ll_slave_set_fifo_mode(i2c->dev, true);
#endif
#else
i2c_ll_slave_init(i2c->dev); i2c_ll_slave_init(i2c->dev);
i2c_ll_slave_set_fifo_mode(i2c->dev, true); i2c_ll_set_fifo_mode(i2c->dev, true);
#endif
i2c_ll_set_slave_addr(i2c->dev, slaveID, false); i2c_ll_set_slave_addr(i2c->dev, slaveID, false);
i2c_ll_set_tout(i2c->dev, I2C_LL_MAX_TIMEOUT); i2c_ll_set_tout(i2c->dev, I2C_LL_MAX_TIMEOUT);
i2c_slave_set_frequency(i2c, frequency); i2c_slave_set_frequency(i2c, frequency);
@ -371,27 +337,15 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t
i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK); i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
i2c_ll_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK); i2c_ll_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2) i2c_ll_set_fifo_mode(i2c->dev, true);
i2c_ll_enable_fifo_mode(i2c->dev, true);
#else
i2c_ll_slave_set_fifo_mode(i2c->dev, true);
#endif
if (!i2c->intr_handle) { if (!i2c->intr_handle) {
uint32_t flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED; uint32_t flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED;
if (i2c->num == 0) { if (i2c->num == 0) {
#if !defined(CONFIG_IDF_TARGET_ESP32P4)
ret = esp_intr_alloc(ETS_I2C_EXT0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); ret = esp_intr_alloc(ETS_I2C_EXT0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle);
#else #if SOC_I2C_NUM > 1
ret = esp_intr_alloc(ETS_I2C0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle);
#endif
#if SOC_HP_I2C_NUM > 1
} else { } else {
#if !defined(CONFIG_IDF_TARGET_ESP32P4)
ret = esp_intr_alloc(ETS_I2C_EXT1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle); ret = esp_intr_alloc(ETS_I2C_EXT1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle);
#else
ret = esp_intr_alloc(ETS_I2C1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle);
#endif
#endif #endif
} }
@ -421,7 +375,7 @@ fail:
} }
esp_err_t i2cSlaveDeinit(uint8_t num) { esp_err_t i2cSlaveDeinit(uint8_t num) {
if (num >= SOC_HP_I2C_NUM) { if (num >= SOC_I2C_NUM) {
log_e("Invalid port num: %u", num); log_e("Invalid port num: %u", num);
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
@ -444,7 +398,7 @@ esp_err_t i2cSlaveDeinit(uint8_t num) {
} }
size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) { size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) {
if (num >= SOC_HP_I2C_NUM) { if (num >= SOC_I2C_NUM) {
log_e("Invalid port num: %u", num); log_e("Invalid port num: %u", num);
return 0; return 0;
} }
@ -561,23 +515,16 @@ static bool i2c_slave_set_frequency(i2c_slave_struct_t *i2c, uint32_t clk_speed)
i2c_hal_clk_config_t clk_cal; i2c_hal_clk_config_t clk_cal;
#if SOC_I2C_SUPPORT_APB #if SOC_I2C_SUPPORT_APB
i2c_ll_master_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal); i2c_ll_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal);
I2C_CLOCK_SRC_ATOMIC() { i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/
i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/
}
#elif SOC_I2C_SUPPORT_XTAL #elif SOC_I2C_SUPPORT_XTAL
#ifndef XTAL_CLK_FREQ i2c_ll_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal);
#define XTAL_CLK_FREQ APB_CLK_FREQ i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_XTAL); /*!< I2C source clock from XTAL, 40M */
#endif
i2c_ll_master_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal);
I2C_CLOCK_SRC_ATOMIC() {
i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_XTAL); /*!< I2C source clock from XTAL, 40M */
}
#endif #endif
i2c_ll_set_txfifo_empty_thr(i2c->dev, a); i2c_ll_set_txfifo_empty_thr(i2c->dev, a);
i2c_ll_set_rxfifo_full_thr(i2c->dev, SOC_I2C_FIFO_LEN - a); i2c_ll_set_rxfifo_full_thr(i2c->dev, SOC_I2C_FIFO_LEN - a);
i2c_ll_master_set_bus_timing(i2c->dev, &clk_cal); i2c_ll_set_bus_timing(i2c->dev, &clk_cal);
i2c_ll_master_set_filter(i2c->dev, 3); i2c_ll_set_filter(i2c->dev, 3);
return true; return true;
} }

View file

@ -15,8 +15,6 @@
#include "esp32-hal-i2c.h" #include "esp32-hal-i2c.h"
#if SOC_I2C_SUPPORTED #if SOC_I2C_SUPPORTED
#include "esp_idf_version.h"
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0)
#include "esp32-hal.h" #include "esp32-hal.h"
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
@ -31,19 +29,6 @@
#include "hal/i2c_ll.h" #include "hal/i2c_ll.h"
#include "driver/i2c.h" #include "driver/i2c.h"
#include "esp32-hal-periman.h" #include "esp32-hal-periman.h"
#include "esp_private/periph_ctrl.h"
#if SOC_PERIPH_CLK_CTRL_SHARED
#define I2C_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define I2C_CLOCK_SRC_ATOMIC()
#endif
#if !SOC_RCC_IS_INDEPENDENT
#define I2C_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define I2C_RCC_ATOMIC()
#endif
#if SOC_I2C_SUPPORT_APB || SOC_I2C_SUPPORT_XTAL #if SOC_I2C_SUPPORT_APB || SOC_I2C_SUPPORT_XTAL
#include "esp_private/esp_clk.h" #include "esp_private/esp_clk.h"
@ -86,7 +71,6 @@ bool i2cIsInit(uint8_t i2c_num) {
} }
esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) { esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
esp_err_t ret = ESP_OK;
if (i2c_num >= SOC_I2C_NUM) { if (i2c_num >= SOC_I2C_NUM) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
@ -106,8 +90,7 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
#endif #endif
if (bus[i2c_num].initialized) { if (bus[i2c_num].initialized) {
log_e("bus is already initialized"); log_e("bus is already initialized");
ret = ESP_FAIL; return ESP_FAIL;
goto init_fail;
} }
if (!frequency) { if (!frequency) {
@ -120,8 +103,7 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SCL, i2cDetachBus); perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SCL, i2cDetachBus);
if (!perimanClearPinBus(sda) || !perimanClearPinBus(scl)) { if (!perimanClearPinBus(sda) || !perimanClearPinBus(scl)) {
ret = ESP_FAIL; return false;
goto init_fail;
} }
log_i("Initializing I2C Master: sda=%d scl=%d freq=%d", sda, scl, frequency); log_i("Initializing I2C Master: sda=%d scl=%d freq=%d", sda, scl, frequency);
@ -135,7 +117,7 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
conf.master.clk_speed = frequency; conf.master.clk_speed = frequency;
conf.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL; //Any one clock source that is available for the specified frequency may be chosen conf.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL; //Any one clock source that is available for the specified frequency may be chosen
ret = i2c_param_config((i2c_port_t)i2c_num, &conf); esp_err_t ret = i2c_param_config((i2c_port_t)i2c_num, &conf);
if (ret != ESP_OK) { if (ret != ESP_OK) {
log_e("i2c_param_config failed"); log_e("i2c_param_config failed");
} else { } else {
@ -151,16 +133,11 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT); i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT);
if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER_SDA, (void *)(i2c_num + 1), i2c_num, -1) if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER_SDA, (void *)(i2c_num + 1), i2c_num, -1)
|| !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER_SCL, (void *)(i2c_num + 1), i2c_num, -1)) { || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER_SCL, (void *)(i2c_num + 1), i2c_num, -1)) {
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock so that i2cDetachBus can execute i2cDeinit
xSemaphoreGive(bus[i2c_num].lock);
#endif
i2cDetachBus((void *)(i2c_num + 1)); i2cDetachBus((void *)(i2c_num + 1));
return ESP_FAIL; return false;
} }
} }
} }
init_fail:
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
//release lock //release lock
xSemaphoreGive(bus[i2c_num].lock); xSemaphoreGive(bus[i2c_num].lock);
@ -403,9 +380,7 @@ esp_err_t i2cSetClock(uint8_t i2c_num, uint32_t frequency) {
periph_rtc_dig_clk8m_enable(); periph_rtc_dig_clk8m_enable();
} }
#endif #endif
I2C_CLOCK_SRC_ATOMIC() { i2c_hal_set_bus_timing(&(hal), frequency, i2c_clk_alloc[src_clk].clk, i2c_clk_alloc[src_clk].clk_freq);
i2c_hal_set_bus_timing(&(hal), frequency, i2c_clk_alloc[src_clk].clk, i2c_clk_alloc[src_clk].clk_freq);
}
bus[i2c_num].frequency = frequency; bus[i2c_num].frequency = frequency;
//Clock Stretching Timeout: 20b:esp32, 5b:esp32-c3, 24b:esp32-s2 //Clock Stretching Timeout: 20b:esp32, 5b:esp32-c3, 24b:esp32-s2
i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT); i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT);
@ -431,5 +406,4 @@ esp_err_t i2cGetClock(uint8_t i2c_num, uint32_t *frequency) {
return ESP_OK; return ESP_OK;
} }
#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0) */
#endif /* SOC_I2C_SUPPORTED */ #endif /* SOC_I2C_SUPPORTED */

View file

@ -19,7 +19,6 @@
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#if SOC_I2C_SUPPORTED #if SOC_I2C_SUPPORTED
#include "esp_idf_version.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -40,10 +39,6 @@ esp_err_t i2cWriteReadNonStop(
); );
bool i2cIsInit(uint8_t i2c_num); bool i2cIsInit(uint8_t i2c_num);
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
void *i2cBusHandle(uint8_t i2c_num);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -22,9 +22,6 @@
#include "soc/gpio_sig_map.h" #include "soc/gpio_sig_map.h"
#include "esp_rom_gpio.h" #include "esp_rom_gpio.h"
#include "hal/ledc_ll.h" #include "hal/ledc_ll.h"
#if SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
#include <math.h>
#endif
#ifdef SOC_LEDC_SUPPORT_HS_MODE #ifdef SOC_LEDC_SUPPORT_HS_MODE
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM << 1) #define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM << 1)
@ -48,96 +45,6 @@ typedef struct {
ledc_periph_t ledc_handle = {0}; ledc_periph_t ledc_handle = {0};
// Helper function to find a timer with matching frequency and resolution
static bool find_matching_timer(uint8_t speed_mode, uint32_t freq, uint8_t resolution, uint8_t *timer_num) {
log_d("Searching for timer with freq=%u, resolution=%u", freq, resolution);
// Check all channels to find one with matching frequency and resolution
for (uint8_t i = 0; i < SOC_GPIO_PIN_COUNT; i++) {
if (!perimanPinIsValid(i)) {
continue;
}
peripheral_bus_type_t type = perimanGetPinBusType(i);
if (type == ESP32_BUS_TYPE_LEDC) {
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(i, ESP32_BUS_TYPE_LEDC);
if (bus != NULL && (bus->channel / SOC_LEDC_CHANNEL_NUM) == speed_mode && bus->freq_hz == freq && bus->channel_resolution == resolution) {
log_d("Found matching timer %u for freq=%u, resolution=%u", bus->timer_num, freq, resolution);
*timer_num = bus->timer_num;
return true;
}
}
}
log_d("No matching timer found for freq=%u, resolution=%u", freq, resolution);
return false;
}
// Helper function to find an unused timer
static bool find_free_timer(uint8_t speed_mode, uint8_t *timer_num) {
// Check which timers are in use
uint8_t used_timers = 0;
for (uint8_t i = 0; i < SOC_GPIO_PIN_COUNT; i++) {
if (!perimanPinIsValid(i)) {
continue;
}
peripheral_bus_type_t type = perimanGetPinBusType(i);
if (type == ESP32_BUS_TYPE_LEDC) {
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(i, ESP32_BUS_TYPE_LEDC);
if (bus != NULL && (bus->channel / SOC_LEDC_CHANNEL_NUM) == speed_mode) {
log_d("Timer %u is in use by channel %u", bus->timer_num, bus->channel);
used_timers |= (1 << bus->timer_num);
}
}
}
#ifndef SOC_LEDC_TIMER_NUM
#define SOC_LEDC_TIMER_NUM 4
#endif
// Find first unused timer
for (uint8_t i = 0; i < SOC_LEDC_TIMER_NUM; i++) {
if (!(used_timers & (1 << i))) {
log_d("Found free timer %u", i);
*timer_num = i;
return true;
}
}
log_e("No free timers available");
return false;
}
// Helper function to remove a channel from a timer and clear timer if no channels are using it
static void remove_channel_from_timer(uint8_t speed_mode, uint8_t timer_num, uint8_t channel) {
log_d("Removing channel %u from timer %u in speed_mode %u", channel, timer_num, speed_mode);
// Check if any other channels are using this timer
bool timer_in_use = false;
for (uint8_t i = 0; i < SOC_GPIO_PIN_COUNT; i++) {
if (!perimanPinIsValid(i)) {
continue;
}
peripheral_bus_type_t type = perimanGetPinBusType(i);
if (type == ESP32_BUS_TYPE_LEDC) {
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(i, ESP32_BUS_TYPE_LEDC);
if (bus != NULL && (bus->channel / SOC_LEDC_CHANNEL_NUM) == speed_mode && bus->timer_num == timer_num && bus->channel != channel) {
log_d("Timer %u is still in use by channel %u", timer_num, bus->channel);
timer_in_use = true;
break;
}
}
}
if (!timer_in_use) {
log_d("No other channels using timer %u, deconfiguring timer", timer_num);
// Stop the timer
ledc_timer_pause(speed_mode, timer_num);
// Deconfigure the timer
ledc_timer_config_t ledc_timer;
memset((void *)&ledc_timer, 0, sizeof(ledc_timer_config_t));
ledc_timer.speed_mode = speed_mode;
ledc_timer.timer_num = timer_num;
ledc_timer.deconfigure = true;
ledc_timer_config(&ledc_timer);
}
}
static bool fade_initialized = false; static bool fade_initialized = false;
static ledc_clk_cfg_t clock_source = LEDC_DEFAULT_CLK; static ledc_clk_cfg_t clock_source = LEDC_DEFAULT_CLK;
@ -174,8 +81,6 @@ static bool ledcDetachBus(void *bus) {
} }
pinMatrixOutDetach(handle->pin, false, false); pinMatrixOutDetach(handle->pin, false, false);
if (!channel_found) { if (!channel_found) {
uint8_t group = (handle->channel / SOC_LEDC_CHANNEL_NUM);
remove_channel_from_timer(group, handle->timer_num, handle->channel % SOC_LEDC_CHANNEL_NUM);
ledc_handle.used_channels &= ~(1UL << handle->channel); ledc_handle.used_channels &= ~(1UL << handle->channel);
} }
free(handle); free(handle);
@ -212,59 +117,32 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c
return false; return false;
} }
uint8_t group = (channel / SOC_LEDC_CHANNEL_NUM); uint8_t group = (channel / 8), timer = ((channel / 2) % 4);
uint8_t timer = 0;
bool channel_used = ledc_handle.used_channels & (1UL << channel); bool channel_used = ledc_handle.used_channels & (1UL << channel);
if (channel_used) { if (channel_used) {
log_i("Channel %u is already set up, given frequency and resolution will be ignored", channel); log_i("Channel %u is already set up, given frequency and resolution will be ignored", channel);
if (ledc_set_pin(pin, group, channel % SOC_LEDC_CHANNEL_NUM) != ESP_OK) { if (ledc_set_pin(pin, group, channel % 8) != ESP_OK) {
log_e("Attaching pin to already used channel failed!"); log_e("Attaching pin to already used channel failed!");
return false; return false;
} }
} else { } else {
// Find a timer with matching frequency and resolution, or a free timer ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = resolution, .freq_hz = freq, .clk_cfg = clock_source};
if (!find_matching_timer(group, freq, resolution, &timer)) { if (ledc_timer_config(&ledc_timer) != ESP_OK) {
if (!find_free_timer(group, &timer)) { log_e("ledc setup failed!");
log_w("No free timers available for speed mode %u", group); return false;
return false;
}
// Configure the timer if we're using a new one
ledc_timer_config_t ledc_timer;
memset((void *)&ledc_timer, 0, sizeof(ledc_timer_config_t));
ledc_timer.speed_mode = group;
ledc_timer.timer_num = timer;
ledc_timer.duty_resolution = resolution;
ledc_timer.freq_hz = freq;
ledc_timer.clk_cfg = clock_source;
if (ledc_timer_config(&ledc_timer) != ESP_OK) {
log_e("ledc setup failed!");
return false;
}
} }
uint32_t duty = ledc_get_duty(group, (channel % SOC_LEDC_CHANNEL_NUM)); uint32_t duty = ledc_get_duty(group, (channel % 8));
ledc_channel_config_t ledc_channel;
memset((void *)&ledc_channel, 0, sizeof(ledc_channel_config_t));
ledc_channel.speed_mode = group;
ledc_channel.channel = (channel % SOC_LEDC_CHANNEL_NUM);
ledc_channel.timer_sel = timer;
ledc_channel.intr_type = LEDC_INTR_DISABLE;
ledc_channel.gpio_num = pin;
ledc_channel.duty = duty;
ledc_channel.hpoint = 0;
ledc_channel_config_t ledc_channel = {
.speed_mode = group, .channel = (channel % 8), .timer_sel = timer, .intr_type = LEDC_INTR_DISABLE, .gpio_num = pin, .duty = duty, .hpoint = 0
};
ledc_channel_config(&ledc_channel); ledc_channel_config(&ledc_channel);
} }
ledc_channel_handle_t *handle = (ledc_channel_handle_t *)malloc(sizeof(ledc_channel_handle_t)); ledc_channel_handle_t *handle = (ledc_channel_handle_t *)malloc(sizeof(ledc_channel_handle_t));
handle->pin = pin; handle->pin = pin;
handle->channel = channel; handle->channel = channel;
handle->timer_num = timer;
handle->freq_hz = freq;
#ifndef SOC_LEDC_SUPPORT_FADE_STOP #ifndef SOC_LEDC_SUPPORT_FADE_STOP
handle->lock = NULL; handle->lock = NULL;
#endif #endif
@ -280,7 +158,7 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c
ledc_handle.used_channels |= 1UL << channel; ledc_handle.used_channels |= 1UL << channel;
} }
if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_LEDC, (void *)handle, channel, timer)) { if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_LEDC, (void *)handle, group, channel)) {
ledcDetachBus((void *)handle); ledcDetachBus((void *)handle);
return false; return false;
} }
@ -297,40 +175,14 @@ bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution) {
} }
uint8_t channel = __builtin_ctz(free_channel); // Convert the free_channel bit to channel number uint8_t channel = __builtin_ctz(free_channel); // Convert the free_channel bit to channel number
// Try the first available channel return ledcAttachChannel(pin, freq, resolution, channel);
if (ledcAttachChannel(pin, freq, resolution, channel)) {
return true;
}
#ifdef SOC_LEDC_SUPPORT_HS_MODE
// If first attempt failed and HS mode is supported, try to find a free channel in group 1
if ((channel / SOC_LEDC_CHANNEL_NUM) == 0) { // First attempt was in group 0
log_d("LEDC: Group 0 channel %u failed, trying to find a free channel in group 1", channel);
// Find free channels specifically in group 1
uint32_t group1_mask = ((1UL << SOC_LEDC_CHANNEL_NUM) - 1) << SOC_LEDC_CHANNEL_NUM;
int group1_free_channel = (~ledc_handle.used_channels) & group1_mask;
if (group1_free_channel != 0) {
uint8_t group1_channel = __builtin_ctz(group1_free_channel);
if (ledcAttachChannel(pin, freq, resolution, group1_channel)) {
return true;
}
}
}
#endif
log_e(
"No free timers available for freq=%u, resolution=%u. To attach a new channel, use the same frequency and resolution as an already attached channel to "
"share its timer.",
freq, resolution
);
return false;
} }
bool ledcWrite(uint8_t pin, uint32_t duty) { bool ledcWrite(uint8_t pin, uint32_t duty) {
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC); ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
if (bus != NULL) { if (bus != NULL) {
uint8_t group = (bus->channel / SOC_LEDC_CHANNEL_NUM), channel = (bus->channel % SOC_LEDC_CHANNEL_NUM); uint8_t group = (bus->channel / 8), channel = (bus->channel % 8);
//Fixing if all bits in resolution is set = LEDC FULL ON //Fixing if all bits in resolution is set = LEDC FULL ON
uint32_t max_duty = (1 << bus->channel_resolution) - 1; uint32_t max_duty = (1 << bus->channel_resolution) - 1;
@ -339,14 +191,8 @@ bool ledcWrite(uint8_t pin, uint32_t duty) {
duty = max_duty + 1; duty = max_duty + 1;
} }
if (ledc_set_duty(group, channel, duty) != ESP_OK) { ledc_set_duty(group, channel, duty);
log_e("ledc_set_duty failed"); ledc_update_duty(group, channel);
return false;
}
if (ledc_update_duty(group, channel) != ESP_OK) {
log_e("ledc_update_duty failed");
return false;
}
return true; return true;
} }
@ -359,11 +205,7 @@ bool ledcWriteChannel(uint8_t channel, uint32_t duty) {
log_e("Channel %u is not available (maximum %u) or not used!", channel, LEDC_CHANNELS); log_e("Channel %u is not available (maximum %u) or not used!", channel, LEDC_CHANNELS);
return false; return false;
} }
uint8_t group = (channel / SOC_LEDC_CHANNEL_NUM); uint8_t group = (channel / 8), timer = ((channel / 2) % 4);
ledc_timer_t timer;
// Get the actual timer being used by this channel
ledc_ll_get_channel_timer(LEDC_LL_GET_HW(), group, (channel % SOC_LEDC_CHANNEL_NUM), &timer);
//Fixing if all bits in resolution is set = LEDC FULL ON //Fixing if all bits in resolution is set = LEDC FULL ON
uint32_t resolution = 0; uint32_t resolution = 0;
@ -375,14 +217,8 @@ bool ledcWriteChannel(uint8_t channel, uint32_t duty) {
duty = max_duty + 1; duty = max_duty + 1;
} }
if (ledc_set_duty(group, channel, duty) != ESP_OK) { ledc_set_duty(group, channel, duty);
log_e("ledc_set_duty failed"); ledc_update_duty(group, channel);
return false;
}
if (ledc_update_duty(group, channel) != ESP_OK) {
log_e("ledc_update_duty failed");
return false;
}
return true; return true;
} }
@ -391,7 +227,7 @@ uint32_t ledcRead(uint8_t pin) {
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC); ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
if (bus != NULL) { if (bus != NULL) {
uint8_t group = (bus->channel / SOC_LEDC_CHANNEL_NUM), channel = (bus->channel % SOC_LEDC_CHANNEL_NUM); uint8_t group = (bus->channel / 8), channel = (bus->channel % 8);
return ledc_get_duty(group, channel); return ledc_get_duty(group, channel);
} }
return 0; return 0;
@ -403,8 +239,8 @@ uint32_t ledcReadFreq(uint8_t pin) {
if (!ledcRead(pin)) { if (!ledcRead(pin)) {
return 0; return 0;
} }
uint8_t group = (bus->channel / SOC_LEDC_CHANNEL_NUM); uint8_t group = (bus->channel / 8), timer = ((bus->channel / 2) % 4);
return ledc_get_freq(group, bus->timer_num); return ledc_get_freq(group, timer);
} }
return 0; return 0;
} }
@ -418,15 +254,9 @@ uint32_t ledcWriteTone(uint8_t pin, uint32_t freq) {
return 0; return 0;
} }
uint8_t group = (bus->channel / SOC_LEDC_CHANNEL_NUM); uint8_t group = (bus->channel / 8), timer = ((bus->channel / 2) % 4);
ledc_timer_config_t ledc_timer; ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = 10, .freq_hz = freq, .clk_cfg = clock_source};
memset((void *)&ledc_timer, 0, sizeof(ledc_timer_config_t));
ledc_timer.speed_mode = group;
ledc_timer.timer_num = bus->timer_num;
ledc_timer.duty_resolution = 10;
ledc_timer.freq_hz = freq;
ledc_timer.clk_cfg = clock_source;
if (ledc_timer_config(&ledc_timer) != ESP_OK) { if (ledc_timer_config(&ledc_timer) != ESP_OK) {
log_e("ledcWriteTone configuration failed!"); log_e("ledcWriteTone configuration failed!");
@ -434,7 +264,7 @@ uint32_t ledcWriteTone(uint8_t pin, uint32_t freq) {
} }
bus->channel_resolution = 10; bus->channel_resolution = 10;
uint32_t res_freq = ledc_get_freq(group, bus->timer_num); uint32_t res_freq = ledc_get_freq(group, timer);
ledcWrite(pin, 0x1FF); ledcWrite(pin, 0x1FF);
return res_freq; return res_freq;
} }
@ -475,22 +305,16 @@ uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution) {
log_e("LEDC pin %u - resolution is zero or it is too big (maximum %u)", pin, LEDC_MAX_BIT_WIDTH); log_e("LEDC pin %u - resolution is zero or it is too big (maximum %u)", pin, LEDC_MAX_BIT_WIDTH);
return 0; return 0;
} }
uint8_t group = (bus->channel / SOC_LEDC_CHANNEL_NUM); uint8_t group = (bus->channel / 8), timer = ((bus->channel / 2) % 4);
ledc_timer_config_t ledc_timer; ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = resolution, .freq_hz = freq, .clk_cfg = clock_source};
memset((void *)&ledc_timer, 0, sizeof(ledc_timer_config_t));
ledc_timer.speed_mode = group;
ledc_timer.timer_num = bus->timer_num;
ledc_timer.duty_resolution = resolution;
ledc_timer.freq_hz = freq;
ledc_timer.clk_cfg = clock_source;
if (ledc_timer_config(&ledc_timer) != ESP_OK) { if (ledc_timer_config(&ledc_timer) != ESP_OK) {
log_e("ledcChangeFrequency failed!"); log_e("ledcChangeFrequency failed!");
return 0; return 0;
} }
bus->channel_resolution = resolution; bus->channel_resolution = resolution;
return ledc_get_freq(group, bus->timer_num); return ledc_get_freq(group, timer);
} }
return 0; return 0;
} }
@ -499,18 +323,11 @@ bool ledcOutputInvert(uint8_t pin, bool out_invert) {
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC); ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
if (bus != NULL) { if (bus != NULL) {
gpio_set_level(pin, out_invert); gpio_set_level(pin, out_invert);
#ifdef CONFIG_IDF_TARGET_ESP32P4
esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT_PAD_OUT0_IDX + ((bus->channel) % SOC_LEDC_CHANNEL_NUM), out_invert, 0);
#else
#ifdef SOC_LEDC_SUPPORT_HS_MODE #ifdef SOC_LEDC_SUPPORT_HS_MODE
esp_rom_gpio_connect_out_signal( esp_rom_gpio_connect_out_signal(pin, ((bus->channel / 8 == 0) ? LEDC_HS_SIG_OUT0_IDX : LEDC_LS_SIG_OUT0_IDX) + ((bus->channel) % 8), out_invert, 0);
pin, ((bus->channel / SOC_LEDC_CHANNEL_NUM == 0) ? LEDC_HS_SIG_OUT0_IDX : LEDC_LS_SIG_OUT0_IDX) + ((bus->channel) % SOC_LEDC_CHANNEL_NUM), out_invert, 0
);
#else #else
esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT0_IDX + ((bus->channel) % SOC_LEDC_CHANNEL_NUM), out_invert, 0); esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT0_IDX + ((bus->channel) % 8), out_invert, 0);
#endif #endif
#endif // ifdef CONFIG_IDF_TARGET_ESP32P4
return true; return true;
} }
return false; return false;
@ -555,7 +372,7 @@ static bool ledcFadeConfig(uint8_t pin, uint32_t start_duty, uint32_t target_dut
} }
#endif #endif
#endif #endif
uint8_t group = (bus->channel / SOC_LEDC_CHANNEL_NUM), channel = (bus->channel % SOC_LEDC_CHANNEL_NUM); uint8_t group = (bus->channel / 8), channel = (bus->channel % 8);
// Initialize fade service. // Initialize fade service.
if (!fade_initialized) { if (!fade_initialized) {
@ -612,161 +429,6 @@ bool ledcFadeWithInterruptArg(uint8_t pin, uint32_t start_duty, uint32_t target_
return ledcFadeConfig(pin, start_duty, target_duty, max_fade_time_ms, userFunc, arg); return ledcFadeConfig(pin, start_duty, target_duty, max_fade_time_ms, userFunc, arg);
} }
#ifdef SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
// Default gamma factor for gamma correction (common value for LEDs)
static float ledcGammaFactor = 2.8;
// Gamma correction LUT support
static const float *ledcGammaLUT = NULL;
static uint16_t ledcGammaLUTSize = 0;
// Global variable to store current resolution for gamma callback
static uint8_t ledcGammaResolution = 13;
bool ledcSetGammaTable(const float *gamma_table, uint16_t size) {
if (gamma_table == NULL || size == 0) {
log_e("Invalid gamma table or size");
return false;
}
ledcGammaLUT = gamma_table;
ledcGammaLUTSize = size;
log_i("Custom gamma LUT set with %u entries", size);
return true;
}
void ledcClearGammaTable(void) {
ledcGammaLUT = NULL;
ledcGammaLUTSize = 0;
log_i("Gamma LUT cleared, using mathematical calculation");
}
void ledcSetGammaFactor(float factor) {
ledcGammaFactor = factor;
}
// Gamma correction calculator function
static uint32_t ledcGammaCorrection(uint32_t duty) {
if (duty == 0) {
return 0;
}
uint32_t max_duty = (1U << ledcGammaResolution) - 1;
if (duty >= (1U << ledcGammaResolution)) {
return max_duty;
}
// Use LUT if provided, otherwise use mathematical calculation
if (ledcGammaLUT != NULL && ledcGammaLUTSize > 0) {
// LUT-based gamma correction
uint32_t lut_index = (duty * (ledcGammaLUTSize - 1)) / max_duty;
if (lut_index >= ledcGammaLUTSize) {
lut_index = ledcGammaLUTSize - 1;
}
float corrected_normalized = ledcGammaLUT[lut_index];
return (uint32_t)(corrected_normalized * max_duty);
} else {
// Mathematical gamma correction
double normalized = (double)duty / (1U << ledcGammaResolution);
double corrected = pow(normalized, ledcGammaFactor);
return (uint32_t)(corrected * (1U << ledcGammaResolution));
}
}
static bool ledcFadeGammaConfig(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void *), void *arg) {
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
if (bus != NULL) {
#ifndef SOC_LEDC_SUPPORT_FADE_STOP
#if !CONFIG_DISABLE_HAL_LOCKS
if (bus->lock == NULL) {
bus->lock = xSemaphoreCreateBinary();
if (bus->lock == NULL) {
log_e("xSemaphoreCreateBinary failed");
return false;
}
xSemaphoreGive(bus->lock);
}
//acquire lock
if (xSemaphoreTake(bus->lock, 0) != pdTRUE) {
log_e("LEDC Fade is still running on pin %u! SoC does not support stopping fade.", pin);
return false;
}
#endif
#endif
uint8_t group = (bus->channel / SOC_LEDC_CHANNEL_NUM), channel = (bus->channel % SOC_LEDC_CHANNEL_NUM);
// Initialize fade service.
if (!fade_initialized) {
ledc_fade_func_install(0);
fade_initialized = true;
}
bus->fn = (voidFuncPtr)userFunc;
bus->arg = arg;
ledc_cbs_t callbacks = {.fade_cb = ledcFnWrapper};
ledc_cb_register(group, channel, &callbacks, (void *)bus);
// Prepare gamma curve fade parameters
ledc_fade_param_config_t fade_params[SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX];
uint32_t actual_fade_ranges = 0;
// Use a moderate number of linear segments for smooth gamma curve
const uint32_t linear_fade_segments = 12;
// Set the global resolution for gamma correction
ledcGammaResolution = bus->channel_resolution;
// Fill multi-fade parameter list using ESP-IDF API
esp_err_t err = ledc_fill_multi_fade_param_list(
group, channel, start_duty, target_duty, linear_fade_segments, max_fade_time_ms, ledcGammaCorrection, SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX, fade_params,
&actual_fade_ranges
);
if (err != ESP_OK) {
log_e("ledc_fill_multi_fade_param_list failed: %s", esp_err_to_name(err));
return false;
}
// Apply the gamma-corrected start duty
uint32_t gamma_start_duty = ledcGammaCorrection(start_duty);
// Set multi-fade parameters
err = ledc_set_multi_fade(group, channel, gamma_start_duty, fade_params, actual_fade_ranges);
if (err != ESP_OK) {
log_e("ledc_set_multi_fade failed: %s", esp_err_to_name(err));
return false;
}
// Start the gamma curve fade
err = ledc_fade_start(group, channel, LEDC_FADE_NO_WAIT);
if (err != ESP_OK) {
log_e("ledc_fade_start failed: %s", esp_err_to_name(err));
return false;
}
log_d("Gamma curve fade started on pin %u: %u -> %u over %dms", pin, start_duty, target_duty, max_fade_time_ms);
} else {
log_e("Pin %u is not attached to LEDC. Call ledcAttach first!", pin);
return false;
}
return true;
}
bool ledcFadeGamma(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms) {
return ledcFadeGammaConfig(pin, start_duty, target_duty, max_fade_time_ms, NULL, NULL);
}
bool ledcFadeGammaWithInterrupt(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, voidFuncPtr userFunc) {
return ledcFadeGammaConfig(pin, start_duty, target_duty, max_fade_time_ms, (voidFuncPtrArg)userFunc, NULL);
}
bool ledcFadeGammaWithInterruptArg(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void *), void *arg) {
return ledcFadeGammaConfig(pin, start_duty, target_duty, max_fade_time_ms, userFunc, arg);
}
#endif /* SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED */
static uint8_t analog_resolution = 8; static uint8_t analog_resolution = 8;
static int analog_frequency = 1000; static int analog_frequency = 1000;
void analogWrite(uint8_t pin, int value) { void analogWrite(uint8_t pin, int value) {

View file

@ -51,8 +51,6 @@ typedef struct {
uint8_t pin; // Pin assigned to channel uint8_t pin; // Pin assigned to channel
uint8_t channel; // Channel number uint8_t channel; // Channel number
uint8_t channel_resolution; // Resolution of channel uint8_t channel_resolution; // Resolution of channel
uint8_t timer_num; // Timer number used by this channel
uint32_t freq_hz; // Frequency configured for this channel
voidFuncPtr fn; voidFuncPtr fn;
void *arg; void *arg;
#ifndef SOC_LEDC_SUPPORT_FADE_STOP #ifndef SOC_LEDC_SUPPORT_FADE_STOP
@ -232,85 +230,6 @@ bool ledcFadeWithInterrupt(uint8_t pin, uint32_t start_duty, uint32_t target_dut
*/ */
bool ledcFadeWithInterruptArg(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void *), void *arg); bool ledcFadeWithInterruptArg(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void *), void *arg);
//Gamma Curve Fade functions - only available on supported chips
#ifdef SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
/**
* @brief Set a custom gamma correction lookup table for gamma curve fading.
* The LUT should contain normalized values (0.0 to 1.0) representing
* the gamma-corrected brightness curve.
*
* @param gamma_table Pointer to array of float values (0.0 to 1.0)
* @param size Number of entries in the lookup table
*
* @return true if gamma table was successfully set, false otherwise.
*
* @note The LUT array must remain valid for as long as gamma fading is used.
* Larger tables provide smoother transitions but use more memory.
*/
bool ledcSetGammaTable(const float *gamma_table, uint16_t size);
/**
* @brief Clear the current gamma correction lookup table.
* After calling this, gamma correction will use mathematical
* calculation with the default gamma factor (2.8).
*/
void ledcClearGammaTable(void);
/**
* @brief Set the gamma factor for gamma correction.
*
* @param factor Gamma factor to use for gamma correction.
*/
void ledcSetGammaFactor(float factor);
/**
* @brief Setup and start a gamma curve fade on a given LEDC pin.
* Gamma correction makes LED brightness changes appear more gradual to human eyes.
*
* @param pin GPIO pin
* @param start_duty initial duty cycle of the fade
* @param target_duty target duty cycle of the fade
* @param max_fade_time_ms maximum fade time in milliseconds
*
* @return true if gamma fade was successfully set and started, false otherwise.
*
* @note This function is only available on ESP32 variants that support gamma curve fading.
*/
bool ledcFadeGamma(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms);
/**
* @brief Setup and start a gamma curve fade on a given LEDC pin with a callback function.
*
* @param pin GPIO pin
* @param start_duty initial duty cycle of the fade
* @param target_duty target duty cycle of the fade
* @param max_fade_time_ms maximum fade time in milliseconds
* @param userFunc callback function to be called after fade is finished
*
* @return true if gamma fade was successfully set and started, false otherwise.
*
* @note This function is only available on ESP32 variants that support gamma curve fading.
*/
bool ledcFadeGammaWithInterrupt(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void));
/**
* @brief Setup and start a gamma curve fade on a given LEDC pin with a callback function and argument.
*
* @param pin GPIO pin
* @param start_duty initial duty cycle of the fade
* @param target_duty target duty cycle of the fade
* @param max_fade_time_ms maximum fade time in milliseconds
* @param userFunc callback function to be called after fade is finished
* @param arg argument to be passed to the callback function
*
* @return true if gamma fade was successfully set and started, false otherwise.
*
* @note This function is only available on ESP32 variants that support gamma curve fading.
*/
bool ledcFadeGammaWithInterruptArg(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void *), void *arg);
#endif // SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -20,7 +20,6 @@ extern "C" {
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_timer.h" #include "esp_timer.h"
#include "rom/ets_sys.h"
#define ARDUHAL_LOG_LEVEL_NONE (0) #define ARDUHAL_LOG_LEVEL_NONE (0)
#define ARDUHAL_LOG_LEVEL_ERROR (1) #define ARDUHAL_LOG_LEVEL_ERROR (1)

View file

@ -32,10 +32,6 @@
#include "esp32c6/rom/gpio.h" #include "esp32c6/rom/gpio.h"
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/gpio.h" #include "esp32h2/rom/gpio.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/gpio.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/gpio.h"
#else #else
#error Target CONFIG_IDF_TARGET is not supported #error Target CONFIG_IDF_TARGET is not supported
#endif #endif

View file

@ -24,16 +24,14 @@
#ifdef CONFIG_APP_ROLLBACK_ENABLE #ifdef CONFIG_APP_ROLLBACK_ENABLE
#include "esp_ota_ops.h" #include "esp_ota_ops.h"
#endif //CONFIG_APP_ROLLBACK_ENABLE #endif //CONFIG_APP_ROLLBACK_ENABLE
#include "esp_private/startup_internal.h" #ifdef CONFIG_BT_ENABLED
#if (defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)) && SOC_BT_SUPPORTED && __has_include("esp_bt.h")
#include "esp_bt.h" #include "esp_bt.h"
#endif #endif //CONFIG_BT_ENABLED
#include <sys/time.h> #include <sys/time.h>
#include "soc/rtc.h" #include "soc/rtc.h"
#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) \ #if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
&& !defined(CONFIG_IDF_TARGET_ESP32C5)
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "soc/syscon_reg.h" #include "soc/apb_ctrl_reg.h"
#endif #endif
#include "esp_task_wdt.h" #include "esp_task_wdt.h"
#include "esp32-hal.h" #include "esp32-hal.h"
@ -55,10 +53,6 @@
#include "esp32c6/rom/rtc.h" #include "esp32c6/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/rtc.h" #include "esp32h2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/rtc.h"
#else #else
#error Target CONFIG_IDF_TARGET is not supported #error Target CONFIG_IDF_TARGET is not supported
@ -153,36 +147,32 @@ void feedLoopWDT() {
#endif #endif
void enableCore0WDT() { void enableCore0WDT() {
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCore(0); TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
if (idle_0 == NULL || esp_task_wdt_add(idle_0) != ESP_OK) { if (idle_0 == NULL || esp_task_wdt_add(idle_0) != ESP_OK) {
log_e("Failed to add Core 0 IDLE task to WDT"); log_e("Failed to add Core 0 IDLE task to WDT");
} }
} }
bool disableCore0WDT() { void disableCore0WDT() {
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCore(0); TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
if (idle_0 == NULL || esp_task_wdt_status(idle_0) || esp_task_wdt_delete(idle_0) != ESP_OK) { if (idle_0 == NULL || esp_task_wdt_delete(idle_0) != ESP_OK) {
log_e("Failed to remove Core 0 IDLE task from WDT"); log_e("Failed to remove Core 0 IDLE task from WDT");
return false;
} }
return true;
} }
#ifndef CONFIG_FREERTOS_UNICORE #ifndef CONFIG_FREERTOS_UNICORE
void enableCore1WDT() { void enableCore1WDT() {
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCore(1); TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
if (idle_1 == NULL || esp_task_wdt_add(idle_1) != ESP_OK) { if (idle_1 == NULL || esp_task_wdt_add(idle_1) != ESP_OK) {
log_e("Failed to add Core 1 IDLE task to WDT"); log_e("Failed to add Core 1 IDLE task to WDT");
} }
} }
bool disableCore1WDT() { void disableCore1WDT() {
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCore(1); TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
if (idle_1 == NULL || esp_task_wdt_status(idle_1) || esp_task_wdt_delete(idle_1) != ESP_OK) { if (idle_1 == NULL || esp_task_wdt_delete(idle_1) != ESP_OK) {
log_e("Failed to remove Core 1 IDLE task from WDT"); log_e("Failed to remove Core 1 IDLE task from WDT");
return false;
} }
return true;
} }
#endif #endif
@ -246,7 +236,7 @@ bool verifyRollbackLater() {
} }
#endif #endif
#if defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED) #ifdef CONFIG_BT_ENABLED
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
//overwritten in esp32-hal-bt.c //overwritten in esp32-hal-bt.c
bool btInUse() __attribute__((weak)); bool btInUse() __attribute__((weak));
@ -259,20 +249,11 @@ extern bool btInUse();
#endif #endif
#endif #endif
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
ESP_SYSTEM_INIT_FN(init_psram_new, CORE, BIT(0), 99) {
psramInit();
return ESP_OK;
}
#endif
void initArduino() { void initArduino() {
//init proper ref tick value for PLL (uncomment if REF_TICK is different than 1MHz) //init proper ref tick value for PLL (uncomment if REF_TICK is different than 1MHz)
//ESP_REG(APB_CTRL_PLL_TICK_CONF_REG) = APB_CLK_FREQ / REF_CLK_FREQ - 1; //ESP_REG(APB_CTRL_PLL_TICK_CONF_REG) = APB_CLK_FREQ / REF_CLK_FREQ - 1;
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM #if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
#ifndef CONFIG_SPIRAM_BOOT_INIT psramInit();
psramAddToHeap();
#endif
#endif #endif
#ifdef CONFIG_APP_ROLLBACK_ENABLE #ifdef CONFIG_APP_ROLLBACK_ENABLE
if (!verifyRollbackLater()) { if (!verifyRollbackLater()) {
@ -308,7 +289,7 @@ void initArduino() {
if (err) { if (err) {
log_e("Failed to initialize NVS! Error: %u", err); log_e("Failed to initialize NVS! Error: %u", err);
} }
#if (defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)) && SOC_BT_SUPPORTED #ifdef CONFIG_BT_ENABLED
if (!btInUse()) { if (!btInUse()) {
esp_bt_controller_mem_release(ESP_BT_MODE_BTDM); esp_bt_controller_mem_release(ESP_BT_MODE_BTDM);
} }

View file

@ -27,16 +27,10 @@
#include "esp32s2/rom/cache.h" #include "esp32s2/rom/cache.h"
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/cache.h" #include "esp32s3/rom/cache.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/cache.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/cache.h"
#else #else
#error Target CONFIG_IDF_TARGET is not supported #error Target CONFIG_IDF_TARGET is not supported
#endif #endif
#define TAG "arduino-psram"
static volatile bool spiramDetected = false; static volatile bool spiramDetected = false;
static volatile bool spiramFailed = false; static volatile bool spiramFailed = false;
@ -58,7 +52,7 @@ bool psramInit() {
uint32_t pkg_ver = chip_ver & 0x7; uint32_t pkg_ver = chip_ver & 0x7;
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) { if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
spiramFailed = true; spiramFailed = true;
ESP_EARLY_LOGW(TAG, "PSRAM not supported!"); log_w("PSRAM not supported!");
return false; return false;
} }
#elif CONFIG_IDF_TARGET_ESP32S2 #elif CONFIG_IDF_TARGET_ESP32S2
@ -68,7 +62,7 @@ bool psramInit() {
#endif #endif
if (esp_psram_init() != ESP_OK) { if (esp_psram_init() != ESP_OK) {
spiramFailed = true; spiramFailed = true;
ESP_EARLY_LOGW(TAG, "PSRAM init failed!"); log_w("PSRAM init failed!");
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
if (pkg_ver != EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) { if (pkg_ver != EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
pinMatrixOutDetach(16, false, false); pinMatrixOutDetach(16, false, false);
@ -77,31 +71,24 @@ bool psramInit() {
#endif #endif
return false; return false;
} }
//testSPIRAM() allows user to bypass SPI RAM test routine //testSPIRAM() allows user to bypass SPI RAM test routine
if (!testSPIRAM()) { if (!testSPIRAM()) {
spiramFailed = true; spiramFailed = true;
ESP_EARLY_LOGE(TAG, "PSRAM test failed!"); log_e("PSRAM test failed!");
return false;
}
//ESP_EARLY_LOGI(TAG, "PSRAM enabled");
#endif /* CONFIG_SPIRAM_BOOT_INIT */
spiramDetected = true;
return true;
}
bool psramAddToHeap() {
if (!spiramDetected) {
log_e("PSRAM not initialized!");
return false; return false;
} }
if (esp_psram_extram_add_to_heap_allocator() != ESP_OK) { if (esp_psram_extram_add_to_heap_allocator() != ESP_OK) {
spiramFailed = true;
log_e("PSRAM could not be added to the heap!"); log_e("PSRAM could not be added to the heap!");
return false; return false;
} }
#if CONFIG_SPIRAM_USE_MALLOC && !CONFIG_ARDUINO_ISR_IRAM #if CONFIG_SPIRAM_USE_MALLOC && !CONFIG_ARDUINO_ISR_IRAM
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL); heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
#endif #endif
log_i("PSRAM added to the heap."); #endif /* CONFIG_SPIRAM_BOOT_INIT */
log_i("PSRAM enabled");
spiramDetected = true;
return true; return true;
} }

View file

@ -21,8 +21,7 @@ extern "C" {
#include "sdkconfig.h" #include "sdkconfig.h"
// Clear flags in Arduino IDE when PSRAM is disabled #ifndef BOARD_HAS_PSRAM
#if defined(ESP32_ARDUINO_LIB_BUILDER) && !defined(BOARD_HAS_PSRAM)
#ifdef CONFIG_SPIRAM_SUPPORT #ifdef CONFIG_SPIRAM_SUPPORT
#undef CONFIG_SPIRAM_SUPPORT #undef CONFIG_SPIRAM_SUPPORT
#endif #endif
@ -32,7 +31,6 @@ extern "C" {
#endif #endif
bool psramInit(); bool psramInit();
bool psramAddToHeap();
bool psramFound(); bool psramFound();
void *ps_malloc(size_t size); void *ps_malloc(size_t size);

View file

@ -206,8 +206,7 @@ bool rmtSetCarrier(int pin, bool carrier_en, bool carrier_level, uint32_t freque
log_w("GPIO %d - RMT Carrier must be a float percentage from 0 to 1. Setting to 50%.", pin); log_w("GPIO %d - RMT Carrier must be a float percentage from 0 to 1. Setting to 50%.", pin);
duty_percent = 0.5; duty_percent = 0.5;
} }
rmt_carrier_config_t carrier_cfg; rmt_carrier_config_t carrier_cfg = {0};
memset((void *)&carrier_cfg, 0, sizeof(rmt_carrier_config_t));
carrier_cfg.duty_cycle = duty_percent; // duty cycle carrier_cfg.duty_cycle = duty_percent; // duty cycle
carrier_cfg.frequency_hz = carrier_en ? frequency_Hz : 0; // carrier frequency in Hz carrier_cfg.frequency_hz = carrier_en ? frequency_Hz : 0; // carrier frequency in Hz
carrier_cfg.flags.polarity_active_low = carrier_level; // carrier modulation polarity level carrier_cfg.flags.polarity_active_low = carrier_level; // carrier modulation polarity level
@ -314,8 +313,7 @@ static bool _rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, bool bl
return false; return false;
} }
rmt_transmit_config_t transmit_cfg; // loop mode disabled rmt_transmit_config_t transmit_cfg = {0}; // loop mode disabled
memset((void *)&transmit_cfg, 0, sizeof(rmt_transmit_config_t));
bool retCode = true; bool retCode = true;
RMT_MUTEX_LOCK(bus); RMT_MUTEX_LOCK(bus);
@ -382,7 +380,6 @@ static bool _rmtRead(int pin, rmt_data_t *data, size_t *num_rmt_symbols, bool wa
// request reading RMT Channel Data // request reading RMT Channel Data
rmt_receive_config_t receive_config; rmt_receive_config_t receive_config;
memset((void *)&receive_config, 0, sizeof(rmt_receive_config_t));
receive_config.signal_range_min_ns = bus->signal_range_min_ns; receive_config.signal_range_min_ns = bus->signal_range_min_ns;
receive_config.signal_range_max_ns = bus->signal_range_max_ns; receive_config.signal_range_max_ns = bus->signal_range_max_ns;
@ -533,7 +530,6 @@ bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t mem_
if (channel_direction == RMT_TX_MODE) { if (channel_direction == RMT_TX_MODE) {
// TX Channel // TX Channel
rmt_tx_channel_config_t tx_cfg; rmt_tx_channel_config_t tx_cfg;
memset((void *)&tx_cfg, 0, sizeof(rmt_tx_channel_config_t));
tx_cfg.gpio_num = pin; tx_cfg.gpio_num = pin;
// CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F80M for C6 -- CLK_XTAL for H2 // CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F80M for C6 -- CLK_XTAL for H2
tx_cfg.clk_src = RMT_CLK_SRC_DEFAULT; tx_cfg.clk_src = RMT_CLK_SRC_DEFAULT;
@ -563,7 +559,6 @@ bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t mem_
} else { } else {
// RX Channel // RX Channel
rmt_rx_channel_config_t rx_cfg; rmt_rx_channel_config_t rx_cfg;
memset((void *)&rx_cfg, 0, sizeof(rmt_rx_channel_config_t));
rx_cfg.gpio_num = pin; rx_cfg.gpio_num = pin;
// CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F80M for C6 -- CLK_XTAL for H2 // CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F80M for C6 -- CLK_XTAL for H2
rx_cfg.clk_src = RMT_CLK_SRC_DEFAULT; rx_cfg.clk_src = RMT_CLK_SRC_DEFAULT;
@ -590,8 +585,7 @@ bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t mem_
} }
// allocate memory for the RMT Copy encoder // allocate memory for the RMT Copy encoder
rmt_copy_encoder_config_t copy_encoder_config; rmt_copy_encoder_config_t copy_encoder_config = {};
memset((void *)&copy_encoder_config, 0, sizeof(rmt_copy_encoder_config_t));
if (rmt_new_copy_encoder(&copy_encoder_config, &bus->rmt_copy_encoder_h) != ESP_OK) { if (rmt_new_copy_encoder(&copy_encoder_config, &bus->rmt_copy_encoder_h) != ESP_OK) {
log_e("GPIO %d - RMT Encoder Memory Allocation error.", pin); log_e("GPIO %d - RMT Encoder Memory Allocation error.", pin);
goto Err; goto Err;

View file

@ -22,15 +22,11 @@
#include "esp_attr.h" #include "esp_attr.h"
#include "soc/spi_reg.h" #include "soc/spi_reg.h"
#include "soc/spi_struct.h" #include "soc/spi_struct.h"
#include "soc/periph_defs.h"
#include "soc/io_mux_reg.h" #include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h" #include "soc/gpio_sig_map.h"
#include "soc/rtc.h" #include "soc/rtc.h"
#ifndef CONFIG_IDF_TARGET_ESP32C5
#include "hal/clk_gate_ll.h" #include "hal/clk_gate_ll.h"
#endif
#include "esp32-hal-periman.h" #include "esp32-hal-periman.h"
#include "esp_private/periph_ctrl.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
@ -59,19 +55,12 @@
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/ets_sys.h" #include "esp32h2/rom/ets_sys.h"
#include "esp32h2/rom/gpio.h" #include "esp32h2/rom/gpio.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/ets_sys.h"
#include "esp32p4/rom/gpio.h"
#include "hal/spi_ll.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/ets_sys.h"
#include "esp32c5/rom/gpio.h"
#else #else
#error Target CONFIG_IDF_TARGET is not supported #error Target CONFIG_IDF_TARGET is not supported
#endif #endif
struct spi_struct_t { struct spi_struct_t {
volatile spi_dev_t *dev; spi_dev_t *dev;
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
SemaphoreHandle_t lock; SemaphoreHandle_t lock;
#endif #endif
@ -80,20 +69,20 @@ struct spi_struct_t {
int8_t miso; int8_t miso;
int8_t mosi; int8_t mosi;
int8_t ss; int8_t ss;
bool ss_invert;
}; };
#if CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32S2
// ESP32S2 // ESP32S2
#define SPI_COUNT (2) #define SPI_COUNT (3)
#define SPI_CLK_IDX(p) ((p == 0) ? FSPICLK_OUT_MUX_IDX : ((p == 1) ? SPI3_CLK_OUT_MUX_IDX : 0)) #define SPI_CLK_IDX(p) ((p == 0) ? SPICLK_OUT_MUX_IDX : ((p == 1) ? FSPICLK_OUT_MUX_IDX : ((p == 2) ? SPI3_CLK_OUT_MUX_IDX : 0)))
#define SPI_MISO_IDX(p) ((p == 0) ? FSPIQ_OUT_IDX : ((p == 1) ? SPI3_Q_OUT_IDX : 0)) #define SPI_MISO_IDX(p) ((p == 0) ? SPIQ_OUT_IDX : ((p == 1) ? FSPIQ_OUT_IDX : ((p == 2) ? SPI3_Q_OUT_IDX : 0)))
#define SPI_MOSI_IDX(p) ((p == 0) ? FSPID_IN_IDX : ((p == 1) ? SPI3_D_IN_IDX : 0)) #define SPI_MOSI_IDX(p) ((p == 0) ? SPID_IN_IDX : ((p == 1) ? FSPID_IN_IDX : ((p == 2) ? SPI3_D_IN_IDX : 0)))
#define SPI_HSPI_SS_IDX(n) ((n == 0) ? SPI3_CS0_OUT_IDX : ((n == 1) ? SPI3_CS1_OUT_IDX : ((n == 2) ? SPI3_CS2_OUT_IDX : 0))) #define SPI_SPI_SS_IDX(n) ((n == 0) ? SPICS0_OUT_IDX : ((n == 1) ? SPICS1_OUT_IDX : 0))
#define SPI_FSPI_SS_IDX(n) ((n == 0) ? FSPICS0_OUT_IDX : ((n == 1) ? FSPICS1_OUT_IDX : ((n == 2) ? FSPICS2_OUT_IDX : 0))) #define SPI_HSPI_SS_IDX(n) ((n == 0) ? SPI3_CS0_OUT_IDX : ((n == 1) ? SPI3_CS1_OUT_IDX : ((n == 2) ? SPI3_CS2_OUT_IDX : SPI3_CS0_OUT_IDX)))
#define SPI_SS_IDX(p, n) ((p == 0) ? SPI_FSPI_SS_IDX(n) : ((p == 1) ? SPI_HSPI_SS_IDX(n) : 0)) #define SPI_FSPI_SS_IDX(n) ((n == 0) ? FSPICS0_OUT_IDX : ((n == 1) ? FSPICS1_OUT_IDX : ((n == 2) ? FSPICS2_OUT_IDX : FSPICS0_OUT_IDX)))
#define SPI_SS_IDX(p, n) ((p == 0) ? SPI_SPI_SS_IDX(n) : ((p == 1) ? SPI_SPI_SS_IDX(n) : ((p == 2) ? SPI_HSPI_SS_IDX(n) : 0)))
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
// ESP32S3 // ESP32S3
@ -103,29 +92,11 @@ struct spi_struct_t {
#define SPI_MISO_IDX(p) ((p == 0) ? FSPIQ_OUT_IDX : ((p == 1) ? SPI3_Q_OUT_IDX : 0)) #define SPI_MISO_IDX(p) ((p == 0) ? FSPIQ_OUT_IDX : ((p == 1) ? SPI3_Q_OUT_IDX : 0))
#define SPI_MOSI_IDX(p) ((p == 0) ? FSPID_IN_IDX : ((p == 1) ? SPI3_D_IN_IDX : 0)) #define SPI_MOSI_IDX(p) ((p == 0) ? FSPID_IN_IDX : ((p == 1) ? SPI3_D_IN_IDX : 0))
#define SPI_HSPI_SS_IDX(n) ((n == 0) ? SPI3_CS0_OUT_IDX : ((n == 1) ? SPI3_CS1_OUT_IDX : ((n == 2) ? SPI3_CS2_OUT_IDX : 0))) #define SPI_HSPI_SS_IDX(n) ((n == 0) ? SPI3_CS0_OUT_IDX : ((n == 1) ? SPI3_CS1_OUT_IDX : 0))
#define SPI_FSPI_SS_IDX(n) ((n == 0) ? FSPICS0_OUT_IDX : ((n == 1) ? FSPICS1_OUT_IDX : ((n == 2) ? FSPICS2_OUT_IDX : 0))) #define SPI_FSPI_SS_IDX(n) ((n == 0) ? FSPICS0_OUT_IDX : ((n == 1) ? FSPICS1_OUT_IDX : 0))
#define SPI_SS_IDX(p, n) ((p == 0) ? SPI_FSPI_SS_IDX(n) : ((p == 1) ? SPI_HSPI_SS_IDX(n) : 0)) #define SPI_SS_IDX(p, n) ((p == 0) ? SPI_FSPI_SS_IDX(n) : ((p == 1) ? SPI_HSPI_SS_IDX(n) : 0))
#elif CONFIG_IDF_TARGET_ESP32P4 #elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
// ESP32P4
#define SPI_COUNT (2) // SPI2 and SPI3. SPI0 and SPI1 are reserved for flash and PSRAM
#define SPI_CLK_IDX(p) ((p == 0) ? SPI2_CK_PAD_OUT_IDX : ((p == 1) ? SPI3_CK_PAD_OUT_IDX : 0))
#define SPI_MISO_IDX(p) ((p == 0) ? SPI2_Q_PAD_OUT_IDX : ((p == 1) ? SPI3_QO_PAD_OUT_IDX : 0))
#define SPI_MOSI_IDX(p) ((p == 0) ? SPI2_D_PAD_IN_IDX : ((p == 1) ? SPI3_D_PAD_IN_IDX : 0))
#define SPI_HSPI_SS_IDX(n) ((n == 0) ? SPI3_CS_PAD_OUT_IDX : ((n == 1) ? SPI3_CS1_PAD_OUT_IDX : ((n == 2) ? SPI3_CS2_PAD_OUT_IDX : 0)))
#define SPI_FSPI_SS_IDX(n) \
((n == 0) ? SPI2_CS_PAD_OUT_IDX \
: ((n == 1) ? SPI2_CS1_PAD_OUT_IDX \
: ((n == 2) ? SPI2_CS2_PAD_OUT_IDX \
: ((n == 3) ? SPI2_CS3_PAD_OUT_IDX : ((n == 4) ? SPI2_CS4_PAD_OUT_IDX : ((n == 5) ? SPI2_CS5_PAD_OUT_IDX : 0))))))
#define SPI_SS_IDX(p, n) ((p == 0) ? SPI_FSPI_SS_IDX(n) : ((p == 1) ? SPI_HSPI_SS_IDX(n) : 0))
#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5
// ESP32C3 // ESP32C3
#define SPI_COUNT (1) #define SPI_COUNT (1)
@ -154,25 +125,27 @@ struct spi_struct_t {
#if CONFIG_DISABLE_HAL_LOCKS #if CONFIG_DISABLE_HAL_LOCKS
#define SPI_MUTEX_LOCK() #define SPI_MUTEX_LOCK()
#define SPI_MUTEX_UNLOCK() #define SPI_MUTEX_UNLOCK()
// clang-format off
static spi_t _spi_bus_array[] = { static spi_t _spi_bus_array[] = {
#if CONFIG_IDF_TARGET_ESP32S2 ||CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 #if CONFIG_IDF_TARGET_ESP32S2
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1, false}, {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 0, -1, -1, -1, -1},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 1, -1, -1, -1, -1, false} {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 1, -1, -1, -1, -1},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 2, -1, -1, -1, -1}
#elif CONFIG_IDF_TARGET_ESP32S3
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 1, -1, -1, -1, -1}
#elif CONFIG_IDF_TARGET_ESP32C2 #elif CONFIG_IDF_TARGET_ESP32C2
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1, false} {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1}
#elif CONFIG_IDF_TARGET_ESP32C3 #elif CONFIG_IDF_TARGET_ESP32C3
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1, false} {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1}
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 #elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
{(spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1, false} {(spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1}
#else #else
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0, -1, -1, -1, -1, false}, {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0, -1, -1, -1, -1},
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1, -1, -1, -1, -1, false}, {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1, -1, -1, -1, -1},
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2, -1, -1, -1, -1, false}, {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2, -1, -1, -1, -1},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3, -1, -1, -1, -1, false} {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3, -1, -1, -1, -1}
#endif #endif
}; };
// clang-format on
#else #else
#define SPI_MUTEX_LOCK() \ #define SPI_MUTEX_LOCK() \
do { \ do { \
@ -180,19 +153,23 @@ static spi_t _spi_bus_array[] = {
#define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock) #define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock)
static spi_t _spi_bus_array[] = { static spi_t _spi_bus_array[] = {
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 #if CONFIG_IDF_TARGET_ESP32S2
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1, false}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 1, -1, -1, -1, -1, false} {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0, -1, -1, -1, -1},
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1, -1, -1, -1, -1},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2, -1, -1, -1, -1}
#elif CONFIG_IDF_TARGET_ESP32S3
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 1, -1, -1, -1, -1}
#elif CONFIG_IDF_TARGET_ESP32C2 #elif CONFIG_IDF_TARGET_ESP32C2
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1, false} {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1}
#elif CONFIG_IDF_TARGET_ESP32C3 #elif CONFIG_IDF_TARGET_ESP32C3
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1, false} {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1}
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 #elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
{(spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1, false} {(spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1}
#else #else
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0, -1, -1, -1, -1, false}, {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0, -1, -1, -1, -1},
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1, -1, -1, -1, -1, false}, {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1, -1, -1, -1, -1},
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2, -1, -1, -1, -1, false}, {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2, -1, -1, -1, -1},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3, -1, -1, -1, -1, false} {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3, -1, -1, -1, -1}
#endif #endif
}; };
#endif #endif
@ -363,7 +340,7 @@ bool spiAttachSS(spi_t *spi, uint8_t ss_num, int8_t ss) {
return false; return false;
} }
pinMode(ss, OUTPUT); pinMode(ss, OUTPUT);
pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, ss_num), spi->ss_invert, false); pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, ss_num), false, false);
spiEnableSSPins(spi, (1 << ss_num)); spiEnableSSPins(spi, (1 << ss_num));
spi->ss = ss; spi->ss = ss;
if (!perimanSetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER_SS, (void *)(spi->num + 1), spi->num, -1)) { if (!perimanSetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER_SS, (void *)(spi->num + 1), spi->num, -1)) {
@ -392,10 +369,11 @@ void spiEnableSSPins(spi_t *spi, uint8_t ss_mask) {
return; return;
} }
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.val &= ~(ss_mask & SPI_SS_MASK_ALL); || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.val &= ~(ss_mask & SPI_SS_MASK_ALL); spi->dev->misc.val &= ~(ss_mask & SPI_SS_MASK_ALL);
#else
spi->dev->pin.val &= ~(ss_mask & SPI_SS_MASK_ALL);
#endif #endif
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
} }
@ -405,10 +383,11 @@ void spiDisableSSPins(spi_t *spi, uint8_t ss_mask) {
return; return;
} }
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.val |= (ss_mask & SPI_SS_MASK_ALL); || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.val |= (ss_mask & SPI_SS_MASK_ALL); spi->dev->misc.val |= (ss_mask & SPI_SS_MASK_ALL);
#else
spi->dev->pin.val |= (ss_mask & SPI_SS_MASK_ALL);
#endif #endif
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
} }
@ -433,21 +412,16 @@ void spiSSDisable(spi_t *spi) {
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
} }
void spiSSInvert(spi_t *spi, bool invert) {
if (spi) {
spi->ss_invert = invert;
}
}
void spiSSSet(spi_t *spi) { void spiSSSet(spi_t *spi) {
if (!spi) { if (!spi) {
return; return;
} }
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.cs_keep_active = 1; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.cs_keep_active = 1; spi->dev->misc.cs_keep_active = 1;
#else
spi->dev->pin.cs_keep_active = 1;
#endif #endif
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
} }
@ -457,10 +431,11 @@ void spiSSClear(spi_t *spi) {
return; return;
} }
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.cs_keep_active = 0; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.cs_keep_active = 0; spi->dev->misc.cs_keep_active = 0;
#else
spi->dev->pin.cs_keep_active = 0;
#endif #endif
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
} }
@ -485,10 +460,11 @@ uint8_t spiGetDataMode(spi_t *spi) {
if (!spi) { if (!spi) {
return 0; return 0;
} }
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
bool idleEdge = spi->dev->pin.ck_idle_edge; || CONFIG_IDF_TARGET_ESP32H2
#else
bool idleEdge = spi->dev->misc.ck_idle_edge; bool idleEdge = spi->dev->misc.ck_idle_edge;
#else
bool idleEdge = spi->dev->pin.ck_idle_edge;
#endif #endif
bool outEdge = spi->dev->user.ck_out_edge; bool outEdge = spi->dev->user.ck_out_edge;
if (idleEdge) { if (idleEdge) {
@ -510,35 +486,39 @@ void spiSetDataMode(spi_t *spi, uint8_t dataMode) {
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
switch (dataMode) { switch (dataMode) {
case SPI_MODE1: case SPI_MODE1:
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.ck_idle_edge = 0; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.ck_idle_edge = 0; spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
#endif #endif
spi->dev->user.ck_out_edge = 1; spi->dev->user.ck_out_edge = 1;
break; break;
case SPI_MODE2: case SPI_MODE2:
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.ck_idle_edge = 1; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.ck_idle_edge = 1; spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
#endif #endif
spi->dev->user.ck_out_edge = 1; spi->dev->user.ck_out_edge = 1;
break; break;
case SPI_MODE3: case SPI_MODE3:
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.ck_idle_edge = 1; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.ck_idle_edge = 1; spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
#endif #endif
spi->dev->user.ck_out_edge = 0; spi->dev->user.ck_out_edge = 0;
break; break;
case SPI_MODE0: case SPI_MODE0:
default: default:
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.ck_idle_edge = 0; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.ck_idle_edge = 0; spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
#endif #endif
spi->dev->user.ck_out_edge = 0; spi->dev->user.ck_out_edge = 0;
break; break;
@ -584,10 +564,11 @@ static void spiInitBus(spi_t *spi) {
spi->dev->slave.trans_done = 0; spi->dev->slave.trans_done = 0;
#endif #endif
spi->dev->slave.val = 0; spi->dev->slave.val = 0;
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.val = 0; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.val = 0; spi->dev->misc.val = 0;
#else
spi->dev->pin.val = 0;
#endif #endif
spi->dev->user.val = 0; spi->dev->user.val = 0;
spi->dev->user1.val = 0; spi->dev->user1.val = 0;
@ -618,7 +599,6 @@ void spiStopBus(spi_t *spi) {
spi_t *spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder) { spi_t *spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder) {
if (spi_num >= SPI_COUNT) { if (spi_num >= SPI_COUNT) {
log_e("SPI bus index %d is out of range", spi_num);
return NULL; return NULL;
} }
@ -645,6 +625,9 @@ spi_t *spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t
} else if (spi_num == HSPI) { } else if (spi_num == HSPI) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
} else {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
} }
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
if (spi_num == FSPI) { if (spi_num == FSPI) {
@ -665,43 +648,18 @@ spi_t *spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
} }
#elif CONFIG_IDF_TARGET_ESP32P4 #elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
if (spi_num == FSPI) {
PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_GPSPI2_MODULE, ref_count) {
if (ref_count == 0) {
PERIPH_RCC_ATOMIC() {
spi_ll_enable_bus_clock(SPI2_HOST, true);
spi_ll_reset_register(SPI2_HOST);
spi_ll_enable_clock(SPI2_HOST, true);
}
}
}
} else if (spi_num == HSPI) {
PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_GPSPI3_MODULE, ref_count) {
if (ref_count == 0) {
PERIPH_RCC_ATOMIC() {
spi_ll_enable_bus_clock(SPI3_HOST, true);
spi_ll_reset_register(SPI3_HOST);
spi_ll_enable_clock(SPI3_HOST, true);
}
}
}
}
#pragma GCC diagnostic pop
#elif defined(__PERIPH_CTRL_ALLOW_LEGACY_API)
periph_ll_reset(PERIPH_SPI2_MODULE); periph_ll_reset(PERIPH_SPI2_MODULE);
periph_ll_enable_clk_clear_rst(PERIPH_SPI2_MODULE); periph_ll_enable_clk_clear_rst(PERIPH_SPI2_MODULE);
#endif #endif
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
spiInitBus(spi); spiInitBus(spi);
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->clk_gate.clk_en = 1; spi->dev->clk_gate.clk_en = 1;
spi->dev->clk_gate.mst_clk_sel = 1; spi->dev->clk_gate.mst_clk_sel = 1;
spi->dev->clk_gate.mst_clk_active = 1; spi->dev->clk_gate.mst_clk_active = 1;
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) #if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2
spi->dev->dma_conf.tx_seg_trans_clr_en = 1; spi->dev->dma_conf.tx_seg_trans_clr_en = 1;
spi->dev->dma_conf.rx_seg_trans_clr_en = 1; spi->dev->dma_conf.rx_seg_trans_clr_en = 1;
spi->dev->dma_conf.dma_seg_trans_en = 0; spi->dev->dma_conf.dma_seg_trans_en = 0;
@ -712,7 +670,7 @@ spi_t *spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t
spi->dev->user.doutdin = 1; spi->dev->user.doutdin = 1;
int i; int i;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[i].val = 0x00000000; spi->dev->data_buf[i].val = 0x00000000;
#else #else
spi->dev->data_buf[i] = 0x00000000; spi->dev->data_buf[i] = 0x00000000;
@ -739,7 +697,7 @@ void spiWaitReady(spi_t *spi) {
#if CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32S2
#define usr_mosi_dbitlen usr_mosi_bit_len #define usr_mosi_dbitlen usr_mosi_bit_len
#define usr_miso_dbitlen usr_miso_bit_len #define usr_miso_dbitlen usr_miso_bit_len
#elif !defined(CONFIG_IDF_TARGET_ESP32) #elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
#define usr_mosi_dbitlen ms_data_bitlen #define usr_mosi_dbitlen ms_data_bitlen
#define usr_miso_dbitlen ms_data_bitlen #define usr_miso_dbitlen ms_data_bitlen
#define mosi_dlen ms_dlen #define mosi_dlen ms_dlen
@ -760,13 +718,13 @@ void spiWrite(spi_t *spi, const uint32_t *data, uint8_t len) {
spi->dev->miso_dlen.usr_miso_dbitlen = 0; spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif #endif
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[i].val = data[i]; spi->dev->data_buf[i].val = data[i];
#else #else
spi->dev->data_buf[i] = data[i]; spi->dev->data_buf[i] = data[i];
#endif #endif
} }
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -787,20 +745,20 @@ void spiTransfer(spi_t *spi, uint32_t *data, uint8_t len) {
spi->dev->mosi_dlen.usr_mosi_dbitlen = (len * 32) - 1; spi->dev->mosi_dlen.usr_mosi_dbitlen = (len * 32) - 1;
spi->dev->miso_dlen.usr_miso_dbitlen = (len * 32) - 1; spi->dev->miso_dlen.usr_miso_dbitlen = (len * 32) - 1;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[i].val = data[i]; spi->dev->data_buf[i].val = data[i];
#else #else
spi->dev->data_buf[i] = data[i]; spi->dev->data_buf[i] = data[i];
#endif #endif
} }
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
spi->dev->cmd.usr = 1; spi->dev->cmd.usr = 1;
while (spi->dev->cmd.usr); while (spi->dev->cmd.usr);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
data[i] = spi->dev->data_buf[i].val; data[i] = spi->dev->data_buf[i].val;
#else #else
data[i] = spi->dev->data_buf[i]; data[i] = spi->dev->data_buf[i];
@ -818,13 +776,13 @@ void spiWriteByte(spi_t *spi, uint8_t data) {
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
spi->dev->miso_dlen.usr_miso_dbitlen = 0; spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif #endif
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -840,18 +798,18 @@ uint8_t spiTransferByte(spi_t *spi, uint8_t data) {
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7; spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
spi->dev->miso_dlen.usr_miso_dbitlen = 7; spi->dev->miso_dlen.usr_miso_dbitlen = 7;
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
spi->dev->cmd.usr = 1; spi->dev->cmd.usr = 1;
while (spi->dev->cmd.usr); while (spi->dev->cmd.usr);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
data = spi->dev->data_buf[0].val & 0xFF; data = spi->dev->data_buf[0].val & 0xFF;
#else #else
data = spi->dev->data_buf[0] & 0xFF; data = spi->dev->data_buf[0] & 0xFF;
@ -881,12 +839,12 @@ void spiWriteWord(spi_t *spi, uint16_t data) {
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
spi->dev->miso_dlen.usr_miso_dbitlen = 0; spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif #endif
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -905,18 +863,18 @@ uint16_t spiTransferWord(spi_t *spi, uint16_t data) {
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15; spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
spi->dev->miso_dlen.usr_miso_dbitlen = 15; spi->dev->miso_dlen.usr_miso_dbitlen = 15;
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
spi->dev->cmd.usr = 1; spi->dev->cmd.usr = 1;
while (spi->dev->cmd.usr); while (spi->dev->cmd.usr);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
data = spi->dev->data_buf[0].val; data = spi->dev->data_buf[0].val;
#else #else
data = spi->dev->data_buf[0]; data = spi->dev->data_buf[0];
@ -940,12 +898,12 @@ void spiWriteLong(spi_t *spi, uint32_t data) {
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
spi->dev->miso_dlen.usr_miso_dbitlen = 0; spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif #endif
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -964,18 +922,18 @@ uint32_t spiTransferLong(spi_t *spi, uint32_t data) {
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31; spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
spi->dev->miso_dlen.usr_miso_dbitlen = 31; spi->dev->miso_dlen.usr_miso_dbitlen = 31;
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
spi->dev->cmd.usr = 1; spi->dev->cmd.usr = 1;
while (spi->dev->cmd.usr); while (spi->dev->cmd.usr);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
data = spi->dev->data_buf[0].val; data = spi->dev->data_buf[0].val;
#else #else
data = spi->dev->data_buf[0]; data = spi->dev->data_buf[0];
@ -1014,14 +972,14 @@ static void __spiTransferBytes(spi_t *spi, const uint8_t *data, uint8_t *out, ui
spi->dev->miso_dlen.usr_miso_dbitlen = ((bytes * 8) - 1); spi->dev->miso_dlen.usr_miso_dbitlen = ((bytes * 8) - 1);
for (i = 0; i < words; i++) { for (i = 0; i < words; i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[i].val = wordsBuf[i]; //copy buffer to spi fifo spi->dev->data_buf[i].val = wordsBuf[i]; //copy buffer to spi fifo
#else #else
spi->dev->data_buf[i] = wordsBuf[i]; //copy buffer to spi fifo spi->dev->data_buf[i] = wordsBuf[i]; //copy buffer to spi fifo
#endif #endif
} }
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -1031,7 +989,7 @@ static void __spiTransferBytes(spi_t *spi, const uint8_t *data, uint8_t *out, ui
if (out) { if (out) {
for (i = 0; i < words; i++) { for (i = 0; i < words; i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
wordsBuf[i] = spi->dev->data_buf[i].val; //copy spi fifo to buffer wordsBuf[i] = spi->dev->data_buf[i].val; //copy spi fifo to buffer
#else #else
wordsBuf[i] = spi->dev->data_buf[i]; //copy spi fifo to buffer wordsBuf[i] = spi->dev->data_buf[i]; //copy spi fifo to buffer
@ -1103,35 +1061,39 @@ void spiTransaction(spi_t *spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bit
spi->dev->clock.val = clockDiv; spi->dev->clock.val = clockDiv;
switch (dataMode) { switch (dataMode) {
case SPI_MODE1: case SPI_MODE1:
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.ck_idle_edge = 0; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.ck_idle_edge = 0; spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
#endif #endif
spi->dev->user.ck_out_edge = 1; spi->dev->user.ck_out_edge = 1;
break; break;
case SPI_MODE2: case SPI_MODE2:
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.ck_idle_edge = 1; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.ck_idle_edge = 1; spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
#endif #endif
spi->dev->user.ck_out_edge = 1; spi->dev->user.ck_out_edge = 1;
break; break;
case SPI_MODE3: case SPI_MODE3:
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.ck_idle_edge = 1; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.ck_idle_edge = 1; spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
#endif #endif
spi->dev->user.ck_out_edge = 0; spi->dev->user.ck_out_edge = 0;
break; break;
case SPI_MODE0: case SPI_MODE0:
default: default:
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
spi->dev->pin.ck_idle_edge = 0; || CONFIG_IDF_TARGET_ESP32H2
#else
spi->dev->misc.ck_idle_edge = 0; spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
#endif #endif
spi->dev->user.ck_out_edge = 0; spi->dev->user.ck_out_edge = 0;
break; break;
@ -1143,7 +1105,7 @@ void spiTransaction(spi_t *spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bit
spi->dev->ctrl.wr_bit_order = 1; spi->dev->ctrl.wr_bit_order = 1;
spi->dev->ctrl.rd_bit_order = 1; spi->dev->ctrl.rd_bit_order = 1;
} }
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
// Sync new config with hardware, fixes https://github.com/espressif/arduino-esp32/issues/9221 // Sync new config with hardware, fixes https://github.com/espressif/arduino-esp32/issues/9221
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
@ -1172,12 +1134,12 @@ void ARDUINO_ISR_ATTR spiWriteByteNL(spi_t *spi, uint8_t data) {
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
spi->dev->miso_dlen.usr_miso_dbitlen = 0; spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif #endif
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -1191,18 +1153,18 @@ uint8_t spiTransferByteNL(spi_t *spi, uint8_t data) {
} }
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7; spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
spi->dev->miso_dlen.usr_miso_dbitlen = 7; spi->dev->miso_dlen.usr_miso_dbitlen = 7;
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
spi->dev->cmd.usr = 1; spi->dev->cmd.usr = 1;
while (spi->dev->cmd.usr); while (spi->dev->cmd.usr);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
data = spi->dev->data_buf[0].val & 0xFF; data = spi->dev->data_buf[0].val & 0xFF;
#else #else
data = spi->dev->data_buf[0] & 0xFF; data = spi->dev->data_buf[0] & 0xFF;
@ -1221,12 +1183,12 @@ void ARDUINO_ISR_ATTR spiWriteShortNL(spi_t *spi, uint16_t data) {
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
spi->dev->miso_dlen.usr_miso_dbitlen = 0; spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif #endif
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -1243,18 +1205,18 @@ uint16_t spiTransferShortNL(spi_t *spi, uint16_t data) {
} }
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15; spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
spi->dev->miso_dlen.usr_miso_dbitlen = 15; spi->dev->miso_dlen.usr_miso_dbitlen = 15;
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
spi->dev->cmd.usr = 1; spi->dev->cmd.usr = 1;
while (spi->dev->cmd.usr); while (spi->dev->cmd.usr);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
data = spi->dev->data_buf[0].val & 0xFFFF; data = spi->dev->data_buf[0].val & 0xFFFF;
#else #else
data = spi->dev->data_buf[0] & 0xFFFF; data = spi->dev->data_buf[0] & 0xFFFF;
@ -1276,12 +1238,12 @@ void ARDUINO_ISR_ATTR spiWriteLongNL(spi_t *spi, uint32_t data) {
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
spi->dev->miso_dlen.usr_miso_dbitlen = 0; spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif #endif
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -1298,18 +1260,18 @@ uint32_t spiTransferLongNL(spi_t *spi, uint32_t data) {
} }
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31; spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
spi->dev->miso_dlen.usr_miso_dbitlen = 31; spi->dev->miso_dlen.usr_miso_dbitlen = 31;
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
spi->dev->cmd.usr = 1; spi->dev->cmd.usr = 1;
while (spi->dev->cmd.usr); while (spi->dev->cmd.usr);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
data = spi->dev->data_buf[0].val; data = spi->dev->data_buf[0].val;
#else #else
data = spi->dev->data_buf[0]; data = spi->dev->data_buf[0];
@ -1340,13 +1302,13 @@ void spiWriteNL(spi_t *spi, const void *data_in, uint32_t len) {
spi->dev->miso_dlen.usr_miso_dbitlen = 0; spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif #endif
for (size_t i = 0; i < c_longs; i++) { for (size_t i = 0; i < c_longs; i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[i].val = data[i]; spi->dev->data_buf[i].val = data[i];
#else #else
spi->dev->data_buf[i] = data[i]; spi->dev->data_buf[i] = data[i];
#endif #endif
} }
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -1379,7 +1341,7 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint
spi->dev->miso_dlen.usr_miso_dbitlen = (c_len * 8) - 1; spi->dev->miso_dlen.usr_miso_dbitlen = (c_len * 8) - 1;
if (data) { if (data) {
for (size_t i = 0; i < c_longs; i++) { for (size_t i = 0; i < c_longs; i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[i].val = data[i]; spi->dev->data_buf[i].val = data[i];
#else #else
spi->dev->data_buf[i] = data[i]; spi->dev->data_buf[i] = data[i];
@ -1387,14 +1349,14 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint
} }
} else { } else {
for (size_t i = 0; i < c_longs; i++) { for (size_t i = 0; i < c_longs; i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[i].val = 0xFFFFFFFF; spi->dev->data_buf[i].val = 0xFFFFFFFF;
#else #else
spi->dev->data_buf[i] = 0xFFFFFFFF; spi->dev->data_buf[i] = 0xFFFFFFFF;
#endif #endif
} }
} }
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -1403,13 +1365,13 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint
if (result) { if (result) {
if (c_len & 3) { if (c_len & 3) {
for (size_t i = 0; i < (c_longs - 1); i++) { for (size_t i = 0; i < (c_longs - 1); i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
result[i] = spi->dev->data_buf[i].val; result[i] = spi->dev->data_buf[i].val;
#else #else
result[i] = spi->dev->data_buf[i]; result[i] = spi->dev->data_buf[i];
#endif #endif
} }
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
uint32_t last_data = spi->dev->data_buf[c_longs - 1].val; uint32_t last_data = spi->dev->data_buf[c_longs - 1].val;
#else #else
uint32_t last_data = spi->dev->data_buf[c_longs - 1]; uint32_t last_data = spi->dev->data_buf[c_longs - 1];
@ -1421,7 +1383,7 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint
} }
} else { } else {
for (size_t i = 0; i < c_longs; i++) { for (size_t i = 0; i < c_longs; i++) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
result[i] = spi->dev->data_buf[i].val; result[i] = spi->dev->data_buf[i].val;
#else #else
result[i] = spi->dev->data_buf[i]; result[i] = spi->dev->data_buf[i];
@ -1463,18 +1425,18 @@ void spiTransferBitsNL(spi_t *spi, uint32_t data, uint32_t *out, uint8_t bits) {
spi->dev->mosi_dlen.usr_mosi_dbitlen = (bits - 1); spi->dev->mosi_dlen.usr_mosi_dbitlen = (bits - 1);
spi->dev->miso_dlen.usr_miso_dbitlen = (bits - 1); spi->dev->miso_dlen.usr_miso_dbitlen = (bits - 1);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[0].val = data; spi->dev->data_buf[0].val = data;
#else #else
spi->dev->data_buf[0] = data; spi->dev->data_buf[0] = data;
#endif #endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
spi->dev->cmd.usr = 1; spi->dev->cmd.usr = 1;
while (spi->dev->cmd.usr); while (spi->dev->cmd.usr);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
data = spi->dev->data_buf[0].val; data = spi->dev->data_buf[0].val;
#else #else
data = spi->dev->data_buf[0]; data = spi->dev->data_buf[0];
@ -1515,34 +1477,34 @@ void ARDUINO_ISR_ATTR spiWritePixelsNL(spi_t *spi, const void *data_in, uint32_t
if (msb) { if (msb) {
if (l_bytes && i == (c_longs - 1)) { if (l_bytes && i == (c_longs - 1)) {
if (l_bytes == 2) { if (l_bytes == 2) {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
MSB_16_SET(spi->dev->data_buf[i].val, data[i]); MSB_16_SET(spi->dev->data_buf[i].val, data[i]);
#else #else
MSB_16_SET(spi->dev->data_buf[i], data[i]); MSB_16_SET(spi->dev->data_buf[i], data[i]);
#endif #endif
} else { } else {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[i].val = data[i] & 0xFF; spi->dev->data_buf[i].val = data[i] & 0xFF;
#else #else
spi->dev->data_buf[i] = data[i] & 0xFF; spi->dev->data_buf[i] = data[i] & 0xFF;
#endif #endif
} }
} else { } else {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
MSB_PIX_SET(spi->dev->data_buf[i].val, data[i]); MSB_PIX_SET(spi->dev->data_buf[i].val, data[i]);
#else #else
MSB_PIX_SET(spi->dev->data_buf[i], data[i]); MSB_PIX_SET(spi->dev->data_buf[i], data[i]);
#endif #endif
} }
} else { } else {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->data_buf[i].val = data[i]; spi->dev->data_buf[i].val = data[i];
#else #else
spi->dev->data_buf[i] = data[i]; spi->dev->data_buf[i] = data[i];
#endif #endif
} }
} }
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
spi->dev->cmd.update = 1; spi->dev->cmd.update = 1;
while (spi->dev->cmd.update); while (spi->dev->cmd.update);
#endif #endif
@ -1566,7 +1528,7 @@ typedef union {
uint32_t clkcnt_l : 6; /*it must be equal to spi_clkcnt_N.*/ uint32_t clkcnt_l : 6; /*it must be equal to spi_clkcnt_N.*/
uint32_t clkcnt_h : 6; /*it must be floor((spi_clkcnt_N+1)/2-1).*/ uint32_t clkcnt_h : 6; /*it must be floor((spi_clkcnt_N+1)/2-1).*/
uint32_t clkcnt_n : 6; /*it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1)*/ uint32_t clkcnt_n : 6; /*it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1)*/
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
uint32_t clkdiv_pre : 4; /*it is pre-divider of spi_clk.*/ uint32_t clkdiv_pre : 4; /*it is pre-divider of spi_clk.*/
uint32_t reserved : 9; /*reserved*/ uint32_t reserved : 9; /*reserved*/
#else #else
@ -1611,7 +1573,7 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq) {
while (calPreVari++ <= 1) { while (calPreVari++ <= 1) {
calPre = (((apb_freq / (reg.clkcnt_n + 1)) / freq) - 1) + calPreVari; calPre = (((apb_freq / (reg.clkcnt_n + 1)) / freq) - 1) + calPreVari;
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
if (calPre > 0xF) { if (calPre > 0xF) {
reg.clkdiv_pre = 0xF; reg.clkdiv_pre = 0xF;
#else #else

View file

@ -27,13 +27,19 @@ extern "C" {
#include <stdbool.h> #include <stdbool.h>
#define SPI_HAS_TRANSACTION #define SPI_HAS_TRANSACTION
#ifdef CONFIG_IDF_TARGET_ESP32
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32S3
#define FSPI 0
#define HSPI 1
#elif CONFIG_IDF_TARGET_ESP32S2
#define FSPI 1 //SPI 1 bus. ESP32S2: for external memory only (can use the same data lines but different SS)
#define HSPI 2 //SPI 2 bus. ESP32S2: external memory or device - it can be matrixed to any pins
#define SPI2 2 // Another name for ESP32S2 SPI 2
#define SPI3 3 //SPI 3 bus. ESP32S2: device only - it can be matrixed to any pins
#elif CONFIG_IDF_TARGET_ESP32
#define FSPI 1 //SPI 1 bus attached to the flash (can use the same data lines but different SS) #define FSPI 1 //SPI 1 bus attached to the flash (can use the same data lines but different SS)
#define HSPI 2 //SPI 2 bus normally mapped to pins 12 - 15, but can be matrixed to any pins #define HSPI 2 //SPI 2 bus normally mapped to pins 12 - 15, but can be matrixed to any pins
#define VSPI 3 //SPI 3 bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins #define VSPI 3 //SPI 3 bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins
#else
#define FSPI 0 // ESP32C2, C3, C6, H2, S2, S3, P4 - SPI 2 bus
#define HSPI 1 // ESP32S2, S3, P4 - SPI 3 bus
#endif #endif
// This defines are not representing the real Divider of the ESP32 // This defines are not representing the real Divider of the ESP32
@ -91,8 +97,6 @@ void spiSSSet(spi_t *spi);
void spiSSClear(spi_t *spi); void spiSSClear(spi_t *spi);
void spiWaitReady(spi_t *spi); void spiWaitReady(spi_t *spi);
//invert hardware SS
void spiSSInvert(spi_t *spi, bool invert);
uint32_t spiGetClockDiv(spi_t *spi); uint32_t spiGetClockDiv(spi_t *spi);
uint8_t spiGetDataMode(spi_t *spi); uint8_t spiGetDataMode(spi_t *spi);

Some files were not shown because too many files have changed in this diff Show more