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]
# 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:
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
builtin = clear,informal,en-GB_to_en-US
check-filenames =

View file

@ -18,7 +18,7 @@ indent_size = 2
indent_style = space
[*.{bash,sh}]
indent_size = 4
indent_size = 2
indent_style = space
[*.{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
attributes:
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.
* 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).

View file

@ -5,7 +5,6 @@ body:
- type: markdown
attributes:
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)
* 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)
@ -40,19 +39,8 @@ body:
label: Version
description: What version of Arduino ESP32 are you running? If possible, consider updating to the latest version.
options:
- latest stable Release (if not listed below)
- latest development Release Candidate (RC-X)
- latest master (checkout manually)
- v3.3.0
- 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
- latest development Release Candidate (RC-X)
- v3.0.4
- v3.0.3
- v3.0.2
@ -80,23 +68,12 @@ body:
- other
validations:
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
id: IDE
attributes:
label: IDE Name
description: What IDE are you using?
placeholder: eg. Arduino IDE, VSCode, Sloeber...
placeholder: eg. Arduino IDE, PlatformIO, Sloeber...
validations:
required: true
- type: input
@ -121,8 +98,8 @@ body:
label: PSRAM enabled
description: Is PSRAM enabled?
options:
- "yes"
- "no"
- 'yes'
- 'no'
validations:
required: true
- type: input
@ -137,8 +114,8 @@ body:
id: Description
attributes:
label: Description
description: Please describe your problem here and expected behavior
placeholder: ex. Can't connect/weird behavior/wrong function/missing parameter..
description: Please describe your problem here and expected behaviour
placeholder: ex. Can't connect/weird behaviour/wrong function/missing parameter..
validations:
required: true
- type: textarea

View file

@ -1,5 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Arduino Core for Espressif Discord Server
url: https://discord.gg/8xY6e9crwv
about: Community Discord server for questions and help
- name: Arduino ESP32 Gitter Channel
url: https://gitter.im/espressif/arduino-esp32
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
#
# 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
@ -13,10 +12,10 @@ set -e
git submodule update --init --recursive
# 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
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
echo "Source files in repo (-) and source files in CMakeLists.txt (+) don't match"

View file

@ -3,9 +3,7 @@
# Get all boards
boards_array=()
boards_list=$(grep '.tarch=' boards.txt)
while read -r line; do
for line in `grep '.tarch=' boards.txt`; do
board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1)
# skip esp32c2 as we dont build libs for it
if [ "$board_name" == "esp32c2" ]; then
@ -14,26 +12,29 @@ while read -r line; do
fi
boards_array+=("espressif:esp32:$board_name")
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
board_count=${#boards_array[@]}
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='['
for board in "${boards_array[@]}"; do
for board in ${boards_array[@]}
do
json_matrix+='"'$board'"'
if [ "$board_count" -gt 1 ]; then
if [ $board_count -gt 1 ]
then
json_matrix+=","
fi
board_count=$((board_count - 1))
board_count=$(($board_count - 1))
done
json_matrix+=']'
echo "$json_matrix"
echo "FQBNS=${json_matrix}" >> "$GITHUB_ENV"
echo $json_matrix
echo "FQBNS=${json_matrix}" >> $GITHUB_ENV
else
echo "FQBNS=" >> "$GITHUB_ENV"
echo "FQBNS=" >> $GITHUB_ENV
fi

View file

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

View file

@ -1,6 +1,6 @@
#!/bin/bash
OSBITS=$(uname -m)
OSBITS=`uname -m`
if [[ "$OSTYPE" == "linux"* ]]; then
export OS_IS_LINUX="1"
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
fi
fi

View file

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

View file

@ -4,7 +4,7 @@
#OSTYPE: 'msys', ARCH: 'x86_64' => win32
#OSTYPE: 'darwin18', ARCH: 'i386' => macos
OSBITS=$(uname -m)
OSBITS=`uname -m`
if [[ "$OSTYPE" == "linux"* ]]; then
export OS_IS_LINUX="1"
ARCHIVE_FORMAT="tar.xz"
@ -77,3 +77,4 @@ if [ ! -d "$ARDUINO_IDE_PATH" ]; then
echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'"
echo ""
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
# This script merges two Arduino Board Manager package json files.
# Usage:
# python merge_packages.py package_esp8266com_index.json version/new/package_esp8266com_index.json
# Written by Ivan Grokhotkov, 2015
# Updated by lucasssvaz to handle Chinese version sorting, 2025
#
from __future__ import print_function
#from distutils.version import LooseVersion
from packaging.version import Version
import re
import json
import sys
def load_package(filename):
pkg = json.load(open(filename))["packages"][0]
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)
pkg = json.load(open(filename))['packages'][0]
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)
return pkg
def merge_objects(versions, obj):
for o in obj:
name = o["name"].encode("ascii")
ver = o["version"].encode("ascii")
if name not in versions:
name = o['name'].encode('ascii')
ver = o['version'].encode('ascii')
if not name in versions:
print("found new object, {0}".format(name), file=sys.stderr)
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)
versions[name][ver] = o
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. 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)
# Normalize ESP release version string (x.x.x) by adding '-rc<MAXINT>' (x.x.x-rc9223372036854775807) to ensure having REL above any RC
# Dummy approach, functional anyway for current ESP package versioning (unlike NormalizedVersion/LooseVersion/StrictVersion & similar crap)
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 "-cn" in str(versionString):
verStr = verStr + "-rc" + str(sys.maxsize // 2)
else:
verStr = verStr + "-rc" + str(sys.maxsize)
if (sys.version_info > (3, 0)): # Python 3
verStr = str(versionString) + '-rc' + str(sys.maxsize)
else: # Python 2
verStr = str(versionString) + '-rc' + str(sys.maxint)
elif len(verParts) != 4:
print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr)
@ -64,35 +56,29 @@ def main(args):
tools = {}
platforms = {}
pkg1 = load_package(args[1])
tools = merge_objects(tools, pkg1["tools"])
platforms = merge_objects(platforms, pkg1["platforms"])
tools = merge_objects(tools, pkg1['tools']);
platforms = merge_objects(platforms, pkg1['platforms']);
pkg2 = load_package(args[2])
tools = merge_objects(tools, pkg2["tools"])
platforms = merge_objects(platforms, pkg2["platforms"])
tools = merge_objects(tools, pkg2['tools']);
platforms = merge_objects(platforms, pkg2['platforms']);
pkg1["tools"] = []
pkg1["platforms"] = []
pkg1['tools'] = []
pkg1['platforms'] = []
for name in tools:
for version in tools[name]:
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 version in platforms[name]:
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"], key=lambda k: LooseVersion(pkgVersionNormalized(k["version"])), reverse=True
# )
#pkg1['platforms'] = sorted(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(
pkg1["platforms"], key=lambda k: Version(pkgVersionNormalized(k["version"])), reverse=True
)
json.dump({'packages':[pkg1]}, sys.stdout, indent=2)
json.dump({"packages": [pkg1]}, sys.stdout, indent=2)
if __name__ == "__main__":
if __name__ == '__main__':
sys.exit(main(sys.argv))

View file

@ -1,13 +1,12 @@
#!/bin/bash
#/bin/bash
set -e
function get_file_size {
function get_file_size(){
local file="$1"
if [[ "$OSTYPE" == "darwin"* ]]; then
eval "$(stat -s "$file")"
eval `stat -s "$file"`
local res="$?"
echo "${st_size:?}"
echo "$st_size"
return $res
else
stat --printf="%s" "$file"
@ -16,32 +15,25 @@ function get_file_size {
}
#git_remove_from_pages <file>
function git_remove_from_pages {
function git_remove_from_pages(){
local path=$1
local info
local type
local sha
local message
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
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=`echo "$info" | jq -r '.type'`
if [ ! $type == "file" ]; then
if [ ! $type == "null" ]; then
echo "Wrong type '$type'"
else
echo "File is not on Pages"
fi
return 0
fi
sha=$(echo "$info" | jq -r '.sha')
message="Deleting "$(basename "$path")
local sha=`echo "$info" | jq -r '.sha'`
local message="Deleting "$(basename $path)
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"
}
function git_upload_to_pages {
function git_upload_to_pages(){
local path=$1
local src=$2
@ -50,50 +42,41 @@ function git_upload_to_pages {
return 1
fi
local info
local type
local message
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=`echo "$info" | jq -r '.type'`
local message=$(basename $path)
local sha=""
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")
type=$(echo "$info" | jq -r '.type')
message=$(basename "$path")
if [ "$type" == "file" ]; then
sha=$(echo "$info" | jq -r '.sha')
if [ $type == "file" ]; then
sha=`echo "$info" | jq -r '.sha'`
sha=",\"sha\":\"$sha\""
message="Updating $message"
elif [ ! "$type" == "null" ]; then
elif [ ! $type == "null" ]; then
>&2 echo "Wrong type '$type'"
return 1
else
message="Creating $message"
fi
content=$(base64 -i "$src")
content=`base64 -i "$src"`
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"
}
function git_safe_upload_to_pages {
function git_safe_upload_to_pages(){
local path=$1
local file="$2"
local name
local size
local upload_res
name=$(basename "$file")
size=$(get_file_size "$file")
if ! upload_res=$(git_upload_to_pages "$path" "$file"); then
local name=$(basename "$file")
local size=`get_file_size "$file"`
local upload_res=`git_upload_to_pages "$path" "$file"`
if [ $? -ne 0 ]; then
>&2 echo "ERROR: Failed to upload '$name' ($?)"
return 1
fi
up_size=$(echo "$upload_res" | jq -r '.content.size')
if [ "$up_size" -ne "$size" ]; then
up_size=`echo "$upload_res" | jq -r '.content.size'`
if [ $up_size -ne $size ]; then
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
#git_delete_asset
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"
function build {
function build(){
local target=$1
local chunk_index=$2
local chunks_cnt=$3
local build_log=$4
local log_level=${5:-none}
local sketches_file=$6
shift 6
local sketches=("$@")
local sketches_file=$5
shift; shift; shift; shift; shift;
local sketches=$*
local BUILD_SKETCH="${SCRIPTS_DIR}/sketch_utils.sh 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
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
args+=("-f" "$sketches_file")
args+=" -f $sketches_file"
fi
if [ "$build_log" -eq 1 ]; then
args+=("-l" "$build_log")
if [ $build_log -eq 1 ]; then
args+=" -l $build_log"
fi
${BUILD_SKETCHES} "${args[@]}"
${BUILD_SKETCHES} ${args}
else
for sketch in "${sketches[@]}"; do
local sargs=("${args[@]}")
local ctags_version
local preprocessor_version
sargs+=("-s" "$(dirname "$sketch")")
for sketch in ${sketches}; do
local sargs="$args -s $(dirname $sketch)"
if [ "$OS_IS_WINDOWS" == "1" ] && [ -d "$ARDUINO_IDE_PATH/tools-builder" ]; then
ctags_version=$(ls "$ARDUINO_IDE_PATH/tools-builder/ctags/")
preprocessor_version=$(ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/")
sargs+=(
"-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"
)
local ctags_version=`ls "$ARDUINO_IDE_PATH/tools-builder/ctags/"`
local preprocessor_version=`ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/"`
win_opts="-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"
sargs+=" ${win_opts}"
fi
${BUILD_SKETCH} "${sargs[@]}"
${BUILD_SKETCH} ${sargs}
done
fi
}
@ -55,13 +53,15 @@ fi
CHUNK_INDEX=$1
CHUNKS_CNT=$2
BUILD_LOG=$3
LOG_LEVEL=$4
SKETCHES_FILE=$5
SKETCHES_FILE=$4
BUILD_PIO=0
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
CHUNK_INDEX=0
CHUNKS_CNT=1
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ] && [ "$CHUNKS_CNT" -ge 2 ]; then
CHUNK_INDEX=$CHUNKS_CNT
elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
BUILD_PIO=1
fi
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
SCRIPTS_DIR="./.github/scripts"
source "${SCRIPTS_DIR}/install-arduino-cli.sh"
source "${SCRIPTS_DIR}/install-arduino-core-esp32.sh"
if [ "$BUILD_PIO" -eq 0 ]; then
source ${SCRIPTS_DIR}/install-arduino-cli.sh
source ${SCRIPTS_DIR}/install-arduino-core-esp32.sh
SKETCHES_ESP32=(
"$ARDUINO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino"
"$ARDUINO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino"
"$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
"$ARDUINO_ESP32_PATH/libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino"
)
SKETCHES_ESP32="\
$ARDUINO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino\
$ARDUINO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino\
$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino\
$ARDUINO_ESP32_PATH/libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino\
"
#create sizes_file
sizes_file="$GITHUB_WORKSPACE/cli_compile_$CHUNK_INDEX.json"
if [ "$BUILD_LOG" -eq 1 ]; then
#create sizes_file and echo start of JSON array with "boards" key
echo "{\"boards\": [" > "$sizes_file"
echo "{\"boards\": [" > $sizes_file
fi
#build sketches for different targets
build "esp32c5" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
build "esp32p4" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
build "esp32s3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
build "esp32s2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
build "esp32c3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
build "esp32c6" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$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[@]}"
build "esp32s3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32s2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32c3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32c6" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32h2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
build "esp32" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "$SKETCHES_ESP32"
if [ "$BUILD_LOG" -eq 1 ]; then
#remove last comma from the last JSON object
sed -i '$ s/,$//' "$sizes_file"
#echo end of JSON array
echo "]}" >> "$sizes_file"
echo "]}" >> $sizes_file
fi
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

View file

@ -1,65 +1,52 @@
#!/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'!"
exit 1
fi
EVENT_JSON=$(cat "$GITHUB_EVENT_PATH")
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
action=$(echo "$EVENT_JSON" | jq -r '.action')
if [ ! "$action" == "published" ]; then
action=`echo $EVENT_JSON | jq -r '.action'`
if [ ! $action == "published" ]; then
echo "Wrong action '$action'. Exiting now..."
exit 0
fi
draft=$(echo "$EVENT_JSON" | jq -r '.release.draft')
if [ "$draft" == "true" ]; then
draft=`echo $EVENT_JSON | jq -r '.release.draft'`
if [ $draft == "true" ]; then
echo "It's a draft release. Exiting now..."
exit 0
fi
RELEASE_PRE=$(echo "$EVENT_JSON" | jq -r '.release.prerelease')
RELEASE_TAG=$(echo "$EVENT_JSON" | jq -r '.release.tag_name')
RELEASE_BRANCH=$(echo "$EVENT_JSON" | jq -r '.release.target_commitish')
RELEASE_ID=$(echo "$EVENT_JSON" | jq -r '.release.id')
RELEASE_PRE=`echo $EVENT_JSON | jq -r '.release.prerelease'`
RELEASE_TAG=`echo $EVENT_JSON | jq -r '.release.tag_name'`
RELEASE_BRANCH=`echo $EVENT_JSON | jq -r '.release.target_commitish'`
RELEASE_ID=`echo $EVENT_JSON | jq -r '.release.id'`
SCRIPTS_DIR="./.github/scripts"
OUTPUT_DIR="$GITHUB_WORKSPACE/build"
PACKAGE_NAME="esp32-$RELEASE_TAG"
PACKAGE_JSON_MERGE="$GITHUB_WORKSPACE/.github/scripts/merge_packages.py"
PACKAGE_JSON_TEMPLATE="$GITHUB_WORKSPACE/package/package_esp32_index.template.json"
PACKAGE_JSON_DEV="package_esp32_dev_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 "Action: $action, Branch: $RELEASE_BRANCH, ID: $RELEASE_ID"
echo "Tag: $RELEASE_TAG, Draft: $draft, Pre-Release: $RELEASE_PRE"
# 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)
VENDOR=$(echo "$RELEASE_BODY" | grep -Pzo '(?s){.*}' | jq -r '.vendor? // 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`
if ! [ -z "${BOARDS}" ]; then echo "Releasing board(s): $BOARDS" ; fi
if ! [ -z "${VENDOR}" ]; then echo "Setting packager: $VENDOR" ; fi
if [ -n "${BOARDS}" ]; then
echo "Releasing board(s): $BOARDS"
fi
if [ -n "${VENDOR}" ]; then
echo "Setting packager: $VENDOR"
fi
function get_file_size {
function get_file_size(){
local file="$1"
if [[ "$OSTYPE" == "darwin"* ]]; then
eval "$(stat -s "$file")"
eval `stat -s "$file"`
local res="$?"
echo "${st_size:?}"
echo "$st_size"
return $res
else
stat --printf="%s" "$file"
@ -67,29 +54,23 @@ function get_file_size {
fi
}
function git_upload_asset {
local name
name=$(basename "$1")
function git_upload_asset(){
local name=$(basename "$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"
}
function git_safe_upload_asset {
function git_safe_upload_asset(){
local file="$1"
local name
local size
local upload_res
name=$(basename "$file")
size=$(get_file_size "$file")
if ! upload_res=$(git_upload_asset "$file"); then
local name=$(basename "$file")
local size=`get_file_size "$file"`
local upload_res=`git_upload_asset "$file"`
if [ $? -ne 0 ]; then
>&2 echo "ERROR: Failed to upload '$name' ($?)"
return 1
fi
up_size=$(echo "$upload_res" | jq -r '.size')
if [ "$up_size" -ne "$size" ]; then
up_size=`echo "$upload_res" | jq -r '.size'`
if [ $up_size -ne $size ]; then
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
#git_delete_asset
return 1
@ -98,7 +79,7 @@ function git_safe_upload_asset {
return $?
}
function git_upload_to_pages {
function git_upload_to_pages(){
local path=$1
local src=$2
@ -107,50 +88,41 @@ function git_upload_to_pages {
return 1
fi
local info
local type
local message
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=`echo "$info" | jq -r '.type'`
local message=$(basename $path)
local sha=""
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")
type=$(echo "$info" | jq -r '.type')
message=$(basename "$path")
if [ "$type" == "file" ]; then
sha=$(echo "$info" | jq -r '.sha')
if [ $type == "file" ]; then
sha=`echo "$info" | jq -r '.sha'`
sha=",\"sha\":\"$sha\""
message="Updating $message"
elif [ ! "$type" == "null" ]; then
elif [ ! $type == "null" ]; then
>&2 echo "Wrong type '$type'"
return 1
else
message="Creating $message"
fi
content=$(base64 -i "$src")
content=`base64 -i "$src"`
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"
}
function git_safe_upload_to_pages {
function git_safe_upload_to_pages(){
local path=$1
local file="$2"
local name
local size
local upload_res
name=$(basename "$file")
size=$(get_file_size "$file")
if ! upload_res=$(git_upload_to_pages "$path" "$file"); then
local name=$(basename "$file")
local size=`get_file_size "$file"`
local upload_res=`git_upload_to_pages "$path" "$file"`
if [ $? -ne 0 ]; then
>&2 echo "ERROR: Failed to upload '$name' ($?)"
return 1
fi
up_size=$(echo "$upload_res" | jq -r '.content.size')
if [ "$up_size" -ne "$size" ]; then
up_size=`echo "$upload_res" | jq -r '.content.size'`
if [ $up_size -ne $size ]; then
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
#git_delete_asset
return 1
@ -159,20 +131,15 @@ function git_safe_upload_to_pages {
return $?
}
function merge_package_json {
function merge_package_json(){
local jsonLink=$1
local jsonOut=$2
local old_json=$OUTPUT_DIR/oldJson.json
local merged_json=$OUTPUT_DIR/mergedJson.json
local error_code=0
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
error_code=$?
if [ $error_code -ne 0 ]; then
echo "ERROR: Download Failed! $error_code"
exit 1
fi
if [ $? -ne 0 ]; then echo "ERROR: Download Failed! $?"; exit 1; fi
echo "Creating new JSON ..."
set +e
@ -180,7 +147,7 @@ function merge_package_json {
set -e
set -v
if [ ! -s "$merged_json" ]; then
if [ ! -s $merged_json ]; then
rm -f "$merged_json"
echo "Nothing to merge"
else
@ -221,10 +188,9 @@ else
done
# Copy only relevant variant files
mkdir "$PKG_DIR/variants/"
board_list=$(cat "${PKG_DIR}"/boards.txt | grep "\.variant=" | cut -d= -f2)
while IFS= read -r variant; do
for variant in `cat ${PKG_DIR}/boards.txt | grep "\.variant=" | cut -d= -f2` ; do
cp -Rf "$GITHUB_WORKSPACE/variants/${variant}" "$PKG_DIR/variants/"
done <<< "$board_list"
done
fi
cp -f "$GITHUB_WORKSPACE/CMakeLists.txt" "$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 -Rf "$GITHUB_WORKSPACE/tools/partitions" "$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
echo "Cleaning up folders ..."
@ -253,8 +219,12 @@ find "$PKG_DIR" -name '*.git*' -type f -delete
##
RVTC_NAME="riscv32-esp-elf-gcc"
RVTC_NEW_NAME="esp-rv32"
X32TC_NAME="xtensa-esp-elf-gcc"
X32TC_NAME="xtensa-esp32-elf-gcc"
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
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/{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/\\{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/\\{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.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
sed -i "/^name=.*/s/$/ ($VENDOR)/" "$PKG_DIR/platform.txt"
fi
# Add header with version information
echo "Generating core_version.h ..."
ver_define=$(echo "$RELEASE_TAG" | tr "[:lower:].\055" "[:upper:]_")
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_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"
ver_define=`echo $RELEASE_TAG | tr "[:lower:].\055" "[:upper:]_"`
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_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"
# Compress package folder
echo "Creating ZIP ..."
pushd "$OUTPUT_DIR" >/dev/null
zip -qr "$PACKAGE_ZIP" "$PACKAGE_NAME"
if [ $? -ne 0 ]; then
echo "ERROR: Failed to create $PACKAGE_ZIP ($?)"
exit 1
fi
if [ $? -ne 0 ]; then echo "ERROR: Failed to create $PACKAGE_ZIP ($?)"; exit 1; fi
# Calculate SHA-256
echo "Calculating SHA sum ..."
PACKAGE_PATH="$OUTPUT_DIR/$PACKAGE_ZIP"
PACKAGE_SHA=$(shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' ')
PACKAGE_SIZE=$(get_file_size "$PACKAGE_ZIP")
PACKAGE_SHA=`shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' '`
PACKAGE_SIZE=`get_file_size "$PACKAGE_ZIP"`
popd >/dev/null
rm -rf "$PKG_DIR"
echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA"
@ -304,7 +274,7 @@ echo
# Upload 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 "Download URL: $PACKAGE_URL"
echo
@ -312,9 +282,9 @@ echo
##
## 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 -d "$RVTC_VERSION" '+%y%m')
RVTC_VERSION=`date -d "$RVTC_VERSION" '+%y%m'`
rvtc_jq_arg="\
(.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\" |\
@ -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\")).name = \"$X32TC_NEW_NAME\" |\
(.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"
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\""
# 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"
# 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
echo "Generating $PACKAGE_JSON_REL ..."
echo "Genarating $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
# Figure out the last release or pre-release
echo "Getting previous releases ..."
releasesJson=$(curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null)
if [ $? -ne 0 ]; then
echo "ERROR: Get Releases Failed! ($?)"
exit 1
fi
releasesJson=`curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null`
if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi
set +e
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
# 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 ..."
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
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 ..."
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
@ -396,32 +363,21 @@ fi
echo "Installing arduino-cli ..."
export PATH="/home/runner/bin:$PATH"
source "${SCRIPTS_DIR}/install-arduino-cli.sh"
# For the Chinese mirror, we can't test the package JSONs as the Chinese mirror might not be updated yet.
source ./.github/scripts/install-arduino-cli.sh
echo "Testing $PACKAGE_JSON_DEV install ..."
echo "Installing esp32 ..."
arduino-cli core install esp32:esp32 --additional-urls "file://$OUTPUT_DIR/$PACKAGE_JSON_DEV"
if [ $? -ne 0 ]; then
echo "ERROR: Failed to install esp32 ($?)"
exit 1
fi
if [ $? -ne 0 ]; then echo "ERROR: Failed to install esp32 ($?)"; exit 1; fi
echo "Compiling example ..."
arduino-cli compile --fqbn esp32:esp32:esp32 "$GITHUB_WORKSPACE"/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino
if [ $? -ne 0 ]; then
echo "ERROR: Failed to compile example ($?)"
exit 1
fi
arduino-cli compile --fqbn esp32:esp32:esp32 $GITHUB_WORKSPACE/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino
if [ $? -ne 0 ]; then echo "ERROR: Failed to compile example ($?)"; exit 1; fi
echo "Uninstalling esp32 ..."
arduino-cli core uninstall esp32:esp32
if [ $? -ne 0 ]; then
echo "ERROR: Failed to uninstall esp32 ($?)"
exit 1
fi
if [ $? -ne 0 ]; then echo "ERROR: Failed to uninstall esp32 ($?)"; exit 1; fi
echo "Test successful!"
@ -430,24 +386,15 @@ if [ "$RELEASE_PRE" == "false" ]; then
echo "Installing esp32 ..."
arduino-cli core install esp32:esp32 --additional-urls "file://$OUTPUT_DIR/$PACKAGE_JSON_REL"
if [ $? -ne 0 ]; then
echo "ERROR: Failed to install esp32 ($?)"
exit 1
fi
if [ $? -ne 0 ]; then echo "ERROR: Failed to install esp32 ($?)"; exit 1; fi
echo "Compiling example ..."
arduino-cli compile --fqbn esp32:esp32:esp32 "$GITHUB_WORKSPACE"/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino
if [ $? -ne 0 ]; then
echo "ERROR: Failed to compile example ($?)"
exit 1
fi
arduino-cli compile --fqbn esp32:esp32:esp32 $GITHUB_WORKSPACE/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino
if [ $? -ne 0 ]; then echo "ERROR: Failed to compile example ($?)"; exit 1; fi
echo "Uninstalling esp32 ..."
arduino-cli core uninstall esp32:esp32
if [ $? -ne 0 ]; then
echo "ERROR: Failed to uninstall esp32 ($?)"
exit 1
fi
if [ $? -ne 0 ]; then echo "ERROR: Failed to uninstall esp32 ($?)"; exit 1; fi
echo "Test successful!"
fi
@ -455,17 +402,13 @@ fi
# Upload package JSONs
echo "Uploading $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 "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 "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
if [ "$RELEASE_PRE" == "false" ]; then
echo "Uploading $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 "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 "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
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

@ -11,39 +11,39 @@ elif [[ $LIB_CHANGED == 'true' ]]; then
echo "Libraries changed. Building only affected sketches."
if [[ $NETWORKING_CHANGED == 'true' ]]; then
echo "Networking libraries changed. Building networking related sketches."
networking_sketches="$(find libraries/WiFi -name '*.ino') "
networking_sketches+="$(find libraries/Ethernet -name '*.ino') "
networking_sketches+="$(find libraries/PPP -name '*.ino') "
networking_sketches+="$(find libraries/NetworkClientSecure -name '*.ino') "
networking_sketches+="$(find libraries/WebServer -name '*.ino') "
networking_sketches="$(find libraries/WiFi -name *.ino) "
networking_sketches+="$(find libraries/Ethernet -name *.ino) "
networking_sketches+="$(find libraries/PPP -name *.ino) "
networking_sketches+="$(find libraries/NetworkClientSecure -name *.ino) "
networking_sketches+="$(find libraries/WebServer -name *.ino) "
fi
if [[ $FS_CHANGED == 'true' ]]; then
echo "FS libraries changed. Building FS related sketches."
fs_sketches="$(find libraries/SD -name '*.ino') "
fs_sketches+="$(find libraries/SD_MMC -name '*.ino') "
fs_sketches+="$(find libraries/SPIFFS -name '*.ino') "
fs_sketches+="$(find libraries/LittleFS -name '*.ino') "
fs_sketches+="$(find libraries/FFat -name '*.ino') "
fs_sketches="$(find libraries/SD -name *.ino) "
fs_sketches+="$(find libraries/SD_MMC -name *.ino) "
fs_sketches+="$(find libraries/SPIFFS -name *.ino) "
fs_sketches+="$(find libraries/LittleFS -name *.ino) "
fs_sketches+="$(find libraries/FFat -name *.ino) "
fi
sketches="$networking_sketches $fs_sketches"
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
echo "Sketch found: $file"
sketches+="$file "
elif [[ "$file" == "$lib/src/"* ]]; then
# If file is inside the src directory, find all sketches in the lib/examples directory
elif [[ $(basename $(dirname $file)) == "src" ]]; then
# If file is in a src directory, find all sketches in the parent/examples directory
echo "Library src file found: $file"
lib=$(dirname $(dirname $file))
if [[ -d $lib/examples ]]; then
lib_sketches=$(find "$lib"/examples -name '*.ino')
lib_sketches=$(find $lib/examples -name *.ino)
sketches+="$lib_sketches "
echo "Library sketches: $lib_sketches"
fi
else
# 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"
sketch=$(find "$(dirname "$file")" -name '*.ino')
sketch=$(find $(dirname $file) -name *.ino)
sketches+="$sketch "
echo "Sketch in example folder: $sketch"
fi
@ -53,9 +53,9 @@ fi
if [[ -n $sketches ]]; then
# Remove duplicates
sketches=$(echo "$sketches" | tr ' ' '\n' | sort | uniq)
sketches=$(echo $sketches | tr ' ' '\n' | sort | uniq)
for sketch in $sketches; do
echo "$sketch" >> sketches_found.txt
echo $sketch >> sketches_found.txt
chunks_count=$((chunks_count+1))
done
echo "Number of sketches found: $chunks_count"
@ -69,16 +69,15 @@ if [[ -n $sketches ]]; then
fi
chunks='["0"'
for i in $(seq 1 $(( chunks_count - 1 )) ); do
for i in $(seq 1 $(( $chunks_count - 1 )) ); do
chunks+=",\"$i\""
done
chunks+="]"
{
echo "build_all=$build_all"
echo "build_libraries=$BUILD_LIBRARIES"
echo "build_static_sketches=$BUILD_STATIC_SKETCHES"
echo "build_idf=$BUILD_IDF"
echo "chunk_count=$chunks_count"
echo "chunks=$chunks"
} >> "$GITHUB_OUTPUT"
echo "build_all=$build_all" >> $GITHUB_OUTPUT
echo "build_libraries=$BUILD_LIBRARIES" >> $GITHUB_OUTPUT
echo "build_static_sketches=$BUILD_STATIC_SKETCHES" >> $GITHUB_OUTPUT
echo "build_idf=$BUILD_IDF" >> $GITHUB_OUTPUT
echo "build_platformio=$BUILD_PLATFORMIO" >> $GITHUB_OUTPUT
echo "chunk_count=$chunks_count" >> $GITHUB_OUTPUT
echo "chunks=$chunks" >> $GITHUB_OUTPUT

View file

@ -1,60 +1,7 @@
#!/bin/bash
if [ -d "$ARDUINO_ESP32_PATH/tools/esp32-arduino-libs" ]; then
SDKCONFIG_DIR="$ARDUINO_ESP32_PATH/tools/esp32-arduino-libs"
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
function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [extra-options]
while [ ! -z "$1" ]; do
case "$1" in
-ai )
shift
@ -88,10 +35,6 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
shift
log_compilation=$1
;;
-d )
shift
debug_level="DebugLevel=$1"
;;
* )
break
;;
@ -99,10 +42,10 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
shift
done
xtra_opts=("$@")
xtra_opts=$*
len=0
if [ -z "$sketchdir" ]; then
if [ -z $sketchdir ]; then
echo "ERROR: Sketch directory not provided"
echo "$USAGE"
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
if [ -z "$fqbn" ]; then
if [ -z "$target" ]; then
if [ -z $fqbn ]; then
if [ -z $target ]; then
echo "ERROR: Unspecified chip"
echo "$USAGE"
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
# 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
# that's the case we build one time for every FQBN.
len=$(jq -r --arg target "$target" '.fqbn[$target] | length' "$sketchdir"/ci.json)
if [ "$len" -gt 0 ]; then
fqbn=$(jq -r --arg target "$target" '.fqbn[$target] | sort' "$sketchdir"/ci.json)
len=`jq -r --arg target $target '.fqbn[$target] | length' $sketchdir/ci.json`
if [ $len -gt 0 ]; then
fqbn=`jq -r --arg target $target '.fqbn[$target] | sort' $sketchdir/ci.json`
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
# build.
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.
# 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')
esp32s2_opts=$(echo "PSRAM=enabled,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
esp32s3_opts=$(echo "PSRAM=opi,USBMode=default,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
esp32c3_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
esp32c6_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
esp32h2_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
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')
esp32_opts="PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio"
esp32s2_opts="PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio"
esp32s3_opts="PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=dio"
esp32c3_opts="PartitionScheme=huge_app,FlashMode=dio"
esp32c6_opts="PartitionScheme=huge_app,FlashMode=dio"
esp32h2_opts="PartitionScheme=huge_app,FlashMode=dio"
# Select the common part of the FQBN based on the target. The rest will be
# appended depending on the passed options.
opt=""
case "$target" in
"esp32")
[ -n "${options:-$esp32_opts}" ] && opt=":${options:-$esp32_opts}"
fqbn="espressif:esp32:esp32$opt"
fqbn="espressif:esp32:esp32:${options:-$esp32_opts}"
;;
"esp32s2")
[ -n "${options:-$esp32s2_opts}" ] && opt=":${options:-$esp32s2_opts}"
fqbn="espressif:esp32:esp32s2$opt"
fqbn="espressif:esp32:esp32s2:${options:-$esp32s2_opts}"
;;
"esp32c3")
[ -n "${options:-$esp32c3_opts}" ] && opt=":${options:-$esp32c3_opts}"
fqbn="espressif:esp32:esp32c3$opt"
fqbn="espressif:esp32:esp32c3:${options:-$esp32c3_opts}"
;;
"esp32s3")
[ -n "${options:-$esp32s3_opts}" ] && opt=":${options:-$esp32s3_opts}"
fqbn="espressif:esp32:esp32s3$opt"
fqbn="espressif:esp32:esp32s3:${options:-$esp32s3_opts}"
;;
"esp32c6")
[ -n "${options:-$esp32c6_opts}" ] && opt=":${options:-$esp32c6_opts}"
fqbn="espressif:esp32:esp32c6$opt"
fqbn="espressif:esp32:esp32c6:${options:-$esp32c6_opts}"
;;
"esp32h2")
[ -n "${options:-$esp32h2_opts}" ] && opt=":${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
fqbn="espressif:esp32:esp32h2:${options:-$esp32h2_opts}"
;;
esac
@ -218,7 +130,7 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
exit 1
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:
# 1. An env variable called ARDUINO_BUILD_DIR.
# 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
# of configuration built in case of a multiconfiguration test.
sketchname=$(basename "$sketchdir")
local has_requirements
sketchname=$(basename $sketchdir)
if [ -f "$sketchdir"/ci.json ]; then
# 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
echo "Skipping $sketchname for target $target"
exit 0
fi
has_requirements=$(check_requirements "$sketchdir" "$SDKCONFIG_DIR/$target/sdkconfig")
if [ "$has_requirements" == "0" ]; then
echo "Target $target does not meet the requirements for $sketchname. Skipping."
exit 0
fi
fi
ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp"
if [ -n "$ARDUINO_BUILD_DIR" ]; then
build_dir="$ARDUINO_BUILD_DIR"
elif [ "$len" -eq 1 ]; then
elif [ $len -eq 1 ]; then
# build_dir="$sketchdir/build"
build_dir="$HOME/.arduino/tests/$target/$sketchname/build.tmp"
build_dir="$HOME/.arduino/tests/$sketchname/build.tmp"
fi
output_file="$HOME/.arduino/cli_compile_output.txt"
sizes_file="$GITHUB_WORKSPACE/cli_compile_$chunk_index.json"
mkdir -p "$ARDUINO_CACHE_DIR"
for i in $(seq 0 $((len - 1))); do
if [ "$len" -ne 1 ]; then
for i in `seq 0 $(($len - 1))`
do
if [ $len -ne 1 ]; then
# build_dir="$sketchdir/build$i"
build_dir="$HOME/.arduino/tests/$target/$sketchname/build$i.tmp"
build_dir="$HOME/.arduino/tests/$sketchname/build$i.tmp"
fi
rm -rf "$build_dir"
mkdir -p "$build_dir"
rm -rf $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
echo "Building $sketchname with arduino-cli and FQBN=$currfqbn"
curroptions=$(echo "$currfqbn" | cut -d':' -f4)
currfqbn=$(echo "$currfqbn" | cut -d':' -f1-3)
"$ide_path"/arduino-cli compile \
curroptions=`echo "$currfqbn" | cut -d':' -f4`
currfqbn=`echo "$currfqbn" | cut -d':' -f1-3`
$ide_path/arduino-cli compile \
--fqbn "$currfqbn" \
--board-options "$curroptions" \
--warnings "all" \
--build-property "compiler.warning_flags.all=-Wall -Werror=all -Wextra" \
--build-cache-path "$ARDUINO_CACHE_DIR" \
--build-path "$build_dir" \
"${xtra_opts[@]}" "${sketchdir}" \
2>&1 | tee "$output_file"
$xtra_opts "${sketchdir}" \
> $output_file
exit_status=${PIPESTATUS[0]}
if [ "$exit_status" -ne 0 ]; then
exit_status=$?
if [ $exit_status -ne 0 ]; then
echo "ERROR: Compilation failed with error code $exit_status"
exit "$exit_status"
exit $exit_status
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
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 '(%)')
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 '(%)')
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 '(%)')
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 '(%)')
# Extract the directory path excluding the filename
directory_path=$(dirname "$sketch")
# Define the constant part
constant_part="/home/runner/Arduino/hardware/espressif/esp32/libraries/"
# Extract the desired substring
lib_sketch_name="${directory_path#"$constant_part"}"
# Extract the desired substring using sed
lib_sketch_name=$(echo "$directory_path" | sed "s|$constant_part||")
#append json file where key is fqbn, sketch name, sizes -> extracted values
echo "{\"name\": \"$lib_sketch_name\",
\"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 "Build path = $build_dir"
"$ide_path"/arduino-builder -compile -logger=human -core-api-version=10810 \
-fqbn=\""$currfqbn"\" \
$ide_path/arduino-builder -compile -logger=human -core-api-version=10810 \
-fqbn=\"$currfqbn\" \
-warnings="all" \
-tools "$ide_path/tools-builder" \
-hardware "$user_path/hardware" \
-libraries "$user_path/libraries" \
-build-cache "$ARDUINO_CACHE_DIR" \
-build-path "$build_dir" \
"${xtra_opts[@]}" "${sketchdir}/${sketchname}.ino"
$xtra_opts "${sketchdir}/${sketchname}.ino"
exit_status=$?
if [ $exit_status -ne 0 ]; then
@ -349,12 +259,10 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
unset options
}
function count_sketches { # count_sketches <path> [target] [file] [ignore-requirements]
function count_sketches(){ # count_sketches <path> [target] [file]
local path=$1
local target=$2
local ignore_requirements=$3
local file=$4
local sketches
local file=$3
if [ $# -lt 1 ]; then
echo "ERROR: Illegal number of parameters"
@ -367,48 +275,40 @@ function count_sketches { # count_sketches <path> [target] [file] [ignore-requir
return 0
fi
if [ -f "$file" ]; then
sketches=$(cat "$file")
if [ -n "$file" ]; then
local sketches=$(cat $file)
else
sketches=$(find "$path" -name '*.ino' | sort)
local sketches=$(find $path -name *.ino | sort)
fi
local sketchnum=0
for sketch in $sketches; do
local sketchdir
local sketchdirname
local sketchname
local has_requirements
sketchdir=$(dirname "$sketch")
sketchdirname=$(basename "$sketchdir")
sketchname=$(basename "$sketch")
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [[ "$sketchdirname.ino" != "$sketchname" ]]; then
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.
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
continue
fi
if [ "$ignore_requirements" != "1" ]; then
has_requirements=$(check_requirements "$sketchdir" "$SDKCONFIG_DIR/$target/sdkconfig")
if [ "$has_requirements" == "0" ]; then
continue
fi
fi
fi
echo "$sketch" >> sketches.txt
sketchnum=$((sketchnum + 1))
echo $sketch >> sketches.txt
sketchnum=$(($sketchnum + 1))
done
return $sketchnum
}
function build_sketches { # build_sketches <ide_path> <user_path> <target> <path> <chunk> <total-chunks> [extra-options]
local args=()
while [ -n "$1" ]; do
function build_sketches(){ # build_sketches <ide_path> <user_path> <target> <path> <chunk> <total-chunks> [extra-options]
local args=""
while [ ! -z "$1" ]; do
case $1 in
-ai )
shift
@ -421,12 +321,12 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
-t )
shift
target=$1
args+=("-t" "$target")
args+=" -t $target"
;;
-fqbn )
shift
fqbn=$1
args+=("-fqbn" "$fqbn")
args+=" -fqbn $fqbn"
;;
-p )
shift
@ -448,11 +348,6 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
shift
sketches_file=$1
;;
-d )
shift
debug_level="$1"
args+=("-d" "$debug_level")
;;
* )
break
;;
@ -460,10 +355,10 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
shift
done
local xtra_opts=("$@")
local xtra_opts=$*
if [ -z "$chunk_index" ] || [ -z "$chunk_max" ]; then
echo "ERROR: Invalid chunk parameters"
echo "ERROR: Invalid chunk paramters"
echo "$USAGE"
exit 1
fi
@ -479,23 +374,20 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
set +e
if [ -n "$sketches_file" ]; then
count_sketches "$path" "$target" "0" "$sketches_file"
count_sketches "$path" "$target" "$sketches_file"
local sketchcount=$?
else
count_sketches "$path" "$target"
local sketchcount=$?
fi
set -e
local sketches
sketches=$(cat sketches.txt)
local sketches=$(cat sketches.txt)
rm -rf sketches.txt
local chunk_size
local all_chunks
chunk_size=$(( sketchcount / chunk_max ))
all_chunks=$(( chunk_max * chunk_size ))
local chunk_size=$(( $sketchcount / $chunk_max ))
local all_chunks=$(( $chunk_max * $chunk_size ))
if [ "$all_chunks" -lt "$sketchcount" ]; then
chunk_size=$(( chunk_size + 1 ))
chunk_size=$(( $chunk_size + 1 ))
fi
local start_index=0
@ -504,20 +396,19 @@ function build_sketches { # build_sketches <ide_path> <user_path> <target> <path
start_index=$chunk_index
end_index=$sketchcount
else
start_index=$(( chunk_index * chunk_size ))
start_index=$(( $chunk_index * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then
echo "No sketches to build for $target in this chunk"
return 0
fi
end_index=$(( $(( chunk_index + 1 )) * chunk_size ))
end_index=$(( $(( $chunk_index + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then
end_index=$sketchcount
fi
fi
local start_num
start_num=$(( start_index + 1 ))
local start_num=$(( $start_index + 1 ))
echo "Found $sketchcount Sketches for target '$target'";
echo "Chunk Index : $chunk_index"
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 "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"
if [ -n "$log_compilation" ]; then
if [ $log_compilation ]; then
#echo board,target and start of sketches to sizes_file json
echo "{ \"board\": \"$log_fqbn\",
echo "{ \"board\": \"$fqbn\",
\"target\": \"$target\",
\"sketches\": [" >> "$sizes_file"
fi
local sketchnum=0
args+=("-ai" "$ide_path" "-au" "$user_path" "-i" "$chunk_index")
if [ -n "$log_compilation" ]; then
args+=("-l" "$log_compilation")
args+=" -ai $ide_path -au $user_path -i $chunk_index"
if [ $log_compilation ]; then
args+=" -l $log_compilation"
fi
for sketch in $sketches; do
local sketchdir
local sketchdirname
sketchdir=$(dirname "$sketch")
sketchdirname=$(basename "$sketchdir")
sketchnum=$((sketchnum + 1))
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
sketchnum=$(($sketchnum + 1))
if [ "$sketchnum" -le "$start_index" ] \
|| [ "$sketchnum" -gt "$end_index" ]; then
continue
fi
echo ""
echo "Building Sketch Index $sketchnum - $sketchdirname"
build_sketch "${args[@]}" -s "$sketchdir" "${xtra_opts[@]}"
build_sketch $args -s $sketchdir $xtra_opts
local result=$?
if [ $result -ne 0 ]; then
return $result
fi
done
if [ -n "$log_compilation" ]; then
if [ $log_compilation ]; then
#remove last comma from json
if [ "$i" -eq $((len - 1)) ]; then
if [ $i -eq $(($len - 1)) ]; then
sed -i '$ s/.$//' "$sizes_file"
fi
#echo end of sketches sizes_file json
@ -586,25 +466,22 @@ Available commands:
count: Count sketches.
build: Build a sketch.
chunk_build: Build a chunk of sketches.
check_requirements: Check if target meets sketch requirements.
"
cmd=$1
shift
if [ -z "$cmd" ]; then
if [ -z $cmd ]; then
echo "ERROR: No command supplied"
echo "$USAGE"
exit 2
fi
case "$cmd" in
"count") count_sketches "$@"
"count") count_sketches $*
;;
"build") build_sketch "$@"
"build") build_sketch $*
;;
"chunk_build") build_sketches "$@"
;;
"check_requirements") check_requirements "$@"
"chunk_build") build_sketches $*
;;
*)
echo "ERROR: Unrecognized command"

View file

@ -10,7 +10,7 @@ USAGE:
Remove build and test generated files
"
function clean {
function clean(){
rm -rf tests/.pytest_cache
find tests/ -type d -name 'build*' -exec rm -rf "{}" \+
find tests/ -type d -name '__pycache__' -exec rm -rf "{}" \+
@ -23,7 +23,7 @@ BUILD_CMD=""
chunk_build=0
while [ -n "$1" ]; do
while [ ! -z "$1" ]; do
case $1 in
-c )
chunk_build=1
@ -51,15 +51,15 @@ while [ -n "$1" ]; do
shift
done
source "${SCRIPTS_DIR}/install-arduino-cli.sh"
source "${SCRIPTS_DIR}/install-arduino-core-esp32.sh"
source ${SCRIPTS_DIR}/install-arduino-cli.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 [ -n "$sketch" ]; then
tmp_sketch_path=$(find tests -name "$sketch".ino)
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")")
tmp_sketch_path=$(find tests -name $sketch.ino)
test_type=$(basename $(dirname $(dirname "$tmp_sketch_path")))
echo "Sketch $sketch test type: $test_type"
test_folder="$PWD/tests/$test_type"
else
@ -71,10 +71,11 @@ fi
if [ $chunk_build -eq 1 ]; then
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
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
args+=("-s" "$test_folder/$sketch")
args+=" -s $test_folder/$sketch"
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,131 +1,106 @@
#!/bin/bash
function run_test {
function run_test() {
local target=$1
local sketch=$2
local options=$3
local erase_flash=$4
local sketchdir
local sketchname
local sketchdir=$(dirname $sketch)
local sketchname=$(basename $sketchdir)
local result=0
local error=0
local sdkconfig_path
local extra_args
local test_type
sketchdir=$(dirname "$sketch")
sketchname=$(basename "$sketchdir")
test_type=$(basename "$(dirname "$sketchdir")")
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
fi
else
len=1
fi
if [ "$len" -eq 1 ]; then
sdkconfig_path="$HOME/.arduino/tests/$target/$sketchname/build.tmp/sdkconfig"
else
sdkconfig_path="$HOME/.arduino/tests/$target/$sketchname/build0.tmp/sdkconfig"
fi
if [ -f "$sketchdir"/ci.json ]; then
# If the target or platform is listed as false, skip the sketch. Otherwise, include it.
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 [ -f $sketchdir/ci.json ]; then
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 [[ $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 "\033[93mSkipping $sketchname test for $target, platform: $platform\033[0m\n"
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
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
fi
else
len=1
fi
if [ "$len" -eq 1 ]; then
if [ $len -eq 1 ]; then
# build_dir="$sketchdir/build"
build_dir="$HOME/.arduino/tests/$target/$sketchname/build.tmp"
build_dir="$HOME/.arduino/tests/$sketchname/build.tmp"
report_file="$sketchdir/$target/$sketchname.xml"
fi
for i in $(seq 0 $((len - 1))); do
for i in `seq 0 $(($len - 1))`
do
fqbn="Default"
if [ "$len" -ne 1 ]; then
fqbn=$(jq -r --arg target "$target" --argjson i "$i" '.fqbn[$target] | sort | .[$i]' "$sketchdir"/ci.json)
elif [ -f "$sketchdir"/ci.json ]; then
has_fqbn=$(jq -r --arg target "$target" '.fqbn[$target]' "$sketchdir"/ci.json)
if [ $len -ne 1 ]; then
fqbn=`jq -r --arg target $target --argjson i $i '.fqbn[$target] | sort | .[$i]' $sketchdir/ci.json`
elif [ -f $sketchdir/ci.json ]; then
has_fqbn=`jq -r --arg target $target '.fqbn[$target]' $sketchdir/ci.json`
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
printf "\033[95mRunning test: %s -- Config: %s\033[0m\n" "$sketchname" "$fqbn"
if [ "$erase_flash" -eq 1 ]; then
esptool.py -c "$target" erase_flash
printf "\033[95mRunning test: $sketchname -- Config: $fqbn\033[0m\n"
if [ $erase_flash -eq 1 ]; then
esptool.py -c $target erase_flash
fi
if [ "$len" -ne 1 ]; then
if [ $len -ne 1 ]; then
# 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"
fi
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
extra_args+=("--wokwi-scenario" "$sketchdir/scenario.yaml")
extra_args+=" --wokwi-scenario $sketchdir/scenario.yaml"
fi
if [[ -f "$sketchdir/diagram.$target.json" ]]; then
extra_args+=("--wokwi-diagram" "$sketchdir/diagram.$target.json")
extra_args+=" --wokwi-diagram $sketchdir/diagram.$target.json"
fi
elif [ $platform == "qemu" ]; then
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
extra_args+=("--qemu-prog-path" "qemu-system-xtensa" "--qemu-cli-args=\"-machine $target -m 4M -nographic\"")
elif [ "$target" == "esp32c3" ]; then
extra_args+=("--qemu-prog-path" "qemu-system-riscv32" "--qemu-cli-args=\"-machine $target -icount 3 -nographic\"")
if [ $target == "esp32" ] || [ $target == "esp32s3" ]; then
extra_args+=" --qemu-prog-path qemu-system-xtensa --qemu-cli-args=\"-machine $target -m 4M -nographic\""
elif [ $target == "esp32c3" ]; then
extra_args+=" --qemu-prog-path qemu-system-riscv32 --qemu-cli-args=\"-machine $target -icount 3 -nographic\""
else
printf "\033[91mUnsupported QEMU target: %s\033[0m\n" "$target"
printf "\033[91mUnsupported QEMU target: $target\033[0m\n"
exit 1
fi
else
extra_args=("--embedded-services" "esp,arduino")
extra_args="--embedded-services esp,arduino"
fi
rm "$sketchdir"/diagram.json 2>/dev/null || true
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}"
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=$?
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 tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args; exit \$?" || result=$?
printf "\n"
if [ $result -ne 0 ]; then
result=0
printf "\033[95mRetrying test: %s -- Config: %s\033[0m\n" "$sketchname" "$i"
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}"
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=$?
printf "\033[95mRetrying test: $sketchname -- Config: $i\033[0m\n"
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 tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args; exit \$?" || result=$?
printf "\n"
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
fi
fi
@ -142,13 +117,13 @@ chunk_run=0
options=0
erase=0
while [ -n "$1" ]; do
while [ ! -z "$1" ]; do
case $1 in
-c )
chunk_run=1
;;
-Q )
if [ ! -d "$QEMU_PATH" ]; then
if [ ! -d $QEMU_PATH ]; then
echo "QEMU path $QEMU_PATH does not exist"
exit 1
fi
@ -201,14 +176,14 @@ while [ -n "$1" ]; do
done
if [ ! $platform == "qemu" ]; then
source "${SCRIPTS_DIR}/install-arduino-ide.sh"
source ${SCRIPTS_DIR}/install-arduino-ide.sh
fi
# 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 [ -n "$sketch" ]; then
tmp_sketch_path=$(find tests -name "$sketch".ino)
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")")
tmp_sketch_path=$(find tests -name $sketch.ino)
test_type=$(basename $(dirname $(dirname "$tmp_sketch_path")))
echo "Sketch $sketch test type: $test_type"
test_folder="$PWD/tests/$test_type"
else
@ -219,11 +194,11 @@ else
fi
if [ $chunk_run -eq 0 ]; then
if [ -z "$sketch" ]; then
if [ -z $sketch ]; then
echo "ERROR: Sketch name is required for single test run"
exit 1
fi
run_test "$target" "$test_folder"/"$sketch"/"$sketch".ino $options $erase
run_test $target $test_folder/$sketch/$sketch.ino $options $erase
exit $?
else
if [ "$chunk_max" -le 0 ]; then
@ -237,17 +212,16 @@ else
fi
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" "1"
${COUNT_SKETCHES} $test_folder $target
sketchcount=$?
set -e
sketches=$(cat sketches.txt)
rm -rf sketches.txt
chunk_size=$(( sketchcount / chunk_max ))
all_chunks=$(( chunk_max * chunk_size ))
chunk_size=$(( $sketchcount / $chunk_max ))
all_chunks=$(( $chunk_max * $chunk_size ))
if [ "$all_chunks" -lt "$sketchcount" ]; then
chunk_size=$(( chunk_size + 1 ))
chunk_size=$(( $chunk_size + 1 ))
fi
start_index=0
@ -256,32 +230,33 @@ else
start_index=$chunk_index
end_index=$sketchcount
else
start_index=$(( chunk_index * chunk_size ))
start_index=$(( $chunk_index * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then
exit 0
fi
end_index=$(( $(( chunk_index + 1 )) * chunk_size ))
end_index=$(( $(( $chunk_index + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then
end_index=$sketchcount
fi
fi
start_num=$(( $start_index + 1 ))
sketchnum=0
error=0
for sketch in $sketches; do
sketchnum=$((sketchnum + 1))
sketchnum=$(($sketchnum + 1))
if [ "$sketchnum" -le "$start_index" ] \
|| [ "$sketchnum" -gt "$end_index" ]; then
continue
fi
printf "\033[95mSketch Index %s\033[0m\n" "$((sketchnum - 1))"
printf "\033[95mSketch Index $(($sketchnum - 1))\033[0m\n"
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
error=$exit_code
fi

View file

@ -1,6 +1,4 @@
#!/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
# "[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"
@ -24,15 +22,7 @@ ESP_ARDUINO_VERSION_MINOR="$2"
ESP_ARDUINO_VERSION_PATCH="$3"
ESP_ARDUINO_VERSION="$ESP_ARDUINO_VERSION_MAJOR.$ESP_ARDUINO_VERSION_MINOR.$ESP_ARDUINO_VERSION_PATCH"
# Get ESP-IDF version from push.yml (this way we can ensure that the version is correct even if the local libs are not up to date)
ESP_IDF_VERSION=$(grep "idf_ver:" .github/workflows/push.yml | sed 's/.*release-v\([^"]*\).*/\1/')
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 "ESP-IDF Version: $ESP_IDF_VERSION"
echo "Updating platform.txt..."
cat platform.txt | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > __platform.txt && mv __platform.txt platform.txt
@ -40,24 +30,13 @@ cat platform.txt | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > __platfor
echo "Updating 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..."
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_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
libraries=$(find libraries -maxdepth 1 -mindepth 1 -type d -exec basename {} \;)
for lib in $libraries; do
for lib in `ls libraries`; do
if [ -f "libraries/$lib/library.properties" ]; then
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"

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

View file

@ -1,6 +1,6 @@
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:
repository_dispatch:
types: [test-boards]
@ -15,12 +15,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
with:
ref: ${{ github.event.client_payload.branch }}
- name: Get boards fqbns
run: bash .github/scripts/find_all_boards.sh
run:
bash .github/scripts/find_all_boards.sh
setup-chunks:
needs: find-boards
@ -32,17 +33,18 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
with:
ref: ${{ github.event.client_payload.branch }}
- run: npm install
- name: Setup jq
uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1
uses: dcarbone/install-jq-action@v1.0.1
- id: set-test-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
@ -64,17 +66,18 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
with:
ref: ${{ github.event.client_payload.branch }}
- name: Echo FQBNS to file
run: echo "$FQBN" > fqbns.json
run:
echo "$FQBN" > fqbns.json
env:
FQBN: ${{ toJSON(matrix.chunk) }}
- 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:
platforms: |
${{ env.REPOSITORY }}
@ -85,4 +88,5 @@ jobs:
enable-warnings-report: false
cli-compile-flags: |
- --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:
pull_request:
paths:
- "boards.txt"
- "libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino"
- ".github/workflows/boards.yml"
- 'boards.txt'
- 'libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino'
- '.github/workflows/boards.yml'
env:
# It's convenient to set variables for values used multiple times in the workflow
@ -22,13 +22,14 @@ jobs:
steps:
# This step makes the contents of the repository available to the workflow
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
- name: Setup jq
uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1
uses: dcarbone/install-jq-action@v1.0.1
- 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:
needs: find-boards
@ -41,13 +42,12 @@ jobs:
name: "espressif:esp32"
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.find-boards.outputs.fqbns) }}
steps:
# This step makes the contents of the repository available to the workflow
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
- name: Check if build.board is uppercase
run: |
@ -60,7 +60,7 @@ jobs:
fi
- name: Get libs cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache@v4
with:
key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }}
path: |
@ -73,7 +73,7 @@ jobs:
./tools/xtensa-*
- 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:
platforms: |
${{ env.REPOSITORY }}
@ -84,5 +84,6 @@ jobs:
cli-compile-flags: |
- --warnings="all"
exit-on-fail: true
sketch-paths: "- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino"
sketch-paths:
"- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino"
verbose: true

View file

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

@ -12,17 +12,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out PR head
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: DangerJS pull request linter
uses: espressif/shared-github-dangerjs@fb17367fd3e8ff7412603b8e946d9b19ffdb2d7f # v1
uses: espressif/shared-github-dangerjs@v1
env:
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

@ -6,14 +6,15 @@ on:
- master
- release/v2.x
paths:
- "docs/**"
- ".github/workflows/docs_build.yml"
- 'docs/**'
- '.github/workflows/docs_build.yml'
pull_request:
paths:
- "docs/**"
- ".github/workflows/docs_build.yml"
- 'docs/**'
- '.github/workflows/docs_build.yml'
jobs:
build-docs:
name: Build ESP-Docs
runs-on: ubuntu-22.04
@ -21,16 +22,14 @@ jobs:
run:
shell: bash
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
- uses: actions/setup-python@v5
with:
cache-dependency-path: docs/requirements.txt
cache: "pip"
python-version: "3.10"
cache: 'pip'
python-version: '3.10'
- name: Build
run: |
sudo apt update
@ -40,9 +39,8 @@ jobs:
cd ./docs
PATH=/home/runner/.local/bin:$PATH pip3 install -r requirements.txt --prefer-binary
PATH=/home/runner/.local/bin:$PATH SPHINXOPTS="-W" build-docs -l en
- name: Archive Docs
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@v4
with:
name: docs
path: docs

View file

@ -10,8 +10,8 @@ on:
- release/v2.x
- master
paths:
- "docs/**"
- ".github/workflows/docs_deploy.yml"
- 'docs/**'
- '.github/workflows/docs_deploy.yml'
jobs:
deploy-prod-docs:
@ -26,17 +26,14 @@ jobs:
run: |
echo "Release workflow failed. Exiting..."
exit 1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
- uses: actions/setup-python@v5
with:
cache-dependency-path: docs/requirements.txt
cache: "pip"
python-version: "3.10"
cache: 'pip'
python-version: '3.10'
- name: Deploy Documentation
env:
# Deploy to production server

View file

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

View file

@ -9,8 +9,7 @@
{
"name": "ArduinoBLE",
"exclude_targets": [
"esp32s2",
"esp32p4"
"esp32s2"
],
"sketch_path": [
"~/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": [
{"source-url": "https://github.com/ESP32Async/AsyncTCP.git"}
{"source-url": "https://github.com/me-no-dev/AsyncTCP.git"}
],
"exclude_targets": [],
"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/CatchAllHandler/CatchAllHandler.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/ChunkResponse/ChunkResponse.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/ChunkRetryResponse/ChunkRetryResponse.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"
"~/Arduino/libraries/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/simple_server/simple_server.ino"
]
},
{

View file

@ -7,7 +7,7 @@ on:
# Schedule weekly builds on every Sunday at 4 am
schedule:
- cron: "0 4 * * SUN"
- cron: '0 4 * * SUN'
concurrency:
group: libs-${{ github.event.pull_request.number || github.ref }}
@ -27,6 +27,7 @@ jobs:
contains(github.event.pull_request.labels.*.name, 'lib_test') ||
(github.event_name == 'schedule' && github.repository == 'espressif/arduino-esp32')
runs-on: ubuntu-latest
env:
REPOSITORY: |
- source-path: '.'
@ -41,7 +42,6 @@ jobs:
- esp32s3
- esp32c6
- esp32h2
- esp32p4
include:
- target: esp32
@ -56,16 +56,15 @@ jobs:
fqbn: espressif:esp32:esp32c6
- target: esp32h2
fqbn: espressif:esp32:esp32h2
- target: esp32p4
fqbn: espressif:esp32:esp32p4
steps:
# This step makes the contents of the repository available to the workflow
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
- 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:
platforms: |
${{ env.REPOSITORY }}
@ -80,7 +79,7 @@ jobs:
- --warnings="all"
- name: Upload artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@v4
with:
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}-${{ matrix.target }}
path: ${{ env.SKETCHES_REPORTS_PATH }}
@ -92,30 +91,32 @@ jobs:
steps:
# Check out repository
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
with:
token: ${{ env.GITHUB_TOKEN }}
fetch-depth: "0"
fetch-depth: '0'
- 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
- name: Download sketches reports artifact
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
uses: actions/download-artifact@v4
with:
pattern: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}-*
merge-multiple: true
path: ${{ env.SKETCHES_REPORTS_PATH }}
- 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:
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
destination-file: ${{ env.RESULT_LIBRARY_TEST_FILE }}
- 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
run: |
@ -136,9 +137,8 @@ jobs:
env:
PR_NUM: ${{ github.event.number }}
run: echo $PR_NUM > pr_num.txt
- name: Upload PR number
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@v4
with:
name: pr_number
path: ./pr_num.txt

View file

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

View file

@ -6,7 +6,7 @@ on:
branches:
- master
pull_request:
types: [opened, reopened, synchronize, labeled]
types: [opened, reopened, synchronize, labeled, unlabeled]
concurrency:
group: pre-commit-${{github.event.pull_request.number || github.ref}}
@ -15,29 +15,21 @@ concurrency:
jobs:
lint:
if: |
github.event_name != 'pull_request' ||
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
runs-on: ubuntu-latest
steps:
- name: Checkout latest commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
with:
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
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
uses: actions/setup-python@v5
with:
cache-dependency-path: tools/pre-commit/requirements.txt
cache: "pip"
cache: 'pip'
python-version: "3.x"
- name: Get Python version hash
@ -46,7 +38,7 @@ jobs:
echo "PY_HASH=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
- name: Restore pre-commit cache
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache/restore@v4
id: restore-cache
with:
path: |
@ -58,13 +50,13 @@ jobs:
- name: Get 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
run: pre-commit run --color=always --show-diff-on-failure --files ${{ steps.changed-files.outputs.all_changed_files }}
- 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' }}
continue-on-error: true
with:
@ -73,7 +65,7 @@ jobs:
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
- 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
if: ${{ always() && github.event_name == 'pull_request' }}
with:

View file

@ -44,12 +44,12 @@ jobs:
- name: Read the pr_num file
id: pr_num_reader
uses: juliangruber/read-file-action@b549046febe0fe86f8cb4f93c24e284433f9ab58 # v1.1.7
uses: juliangruber/read-file-action@v1
with:
path: ./artifacts/workflows/pr_num.txt
- 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:
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
github-token: ${{ env.GITHUB_TOKEN }}

View file

@ -11,11 +11,11 @@ env:
jobs:
sizes-test-results:
name: Sizes Comparison Results
name: Sizes Comparsion Results
runs-on: ubuntu-latest
steps:
- name: Checkout gh-pages branch
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Checkout code
uses: actions/checkout@v4 # This step checks out the repository's code at gh-pages branch
with:
ref: gh-pages
@ -34,14 +34,15 @@ jobs:
mv v2.x_cli_compile/*.json artifacts/sizes-report/master/
- 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:
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
github-token: ${{ env.GITHUB_TOKEN }}
destination-file: ${{ env.RESULT_SIZES_TEST_FILE }}
- 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
run: |

View file

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

View file

@ -2,57 +2,31 @@ name: Compilation Tests
on:
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:
branches:
- master
- release/*
- release/v2.x
pull_request:
paths:
- "cores/**"
- "libraries/**"
- "!libraries/**.md"
- "!libraries/**.txt"
- "!libraries/**.properties"
- "!libraries/**.py"
- "package/**"
- "idf_component_examples/**"
- "tools/**.py"
- "platform.txt"
- "programmers.txt"
- "idf_component.yml"
- "Kconfig.projbuild"
- "package.json"
- "CMakeLists.txt"
- ".github/workflows/push.yml"
- ".github/scripts/**"
- "!.github/scripts/find_*"
- "!.github/scripts/on-release.sh"
- "!.github/scripts/tests_*"
- "!.github/scripts/upload_*"
- "variants/esp32/**/*"
- "variants/esp32c3/**/*"
- "variants/esp32c5/**/*"
- "variants/esp32c6/**/*"
- "variants/esp32h2/**/*"
- "variants/esp32p4/**/*"
- "variants/esp32s2/**/*"
- "variants/esp32s3/**/*"
- 'cores/**'
- 'libraries/**'
- '!libraries/**.md'
- '!libraries/**.txt'
- '!libraries/**.properties'
- '!libraries/**.py'
- 'package/**'
- 'tools/**.py'
- 'platform.txt'
- 'programmers.txt'
- 'idf_component.yml'
- 'Kconfig.projbuild'
- 'package.json'
- '.github/workflows/push.yml'
- '.github/scripts/**'
- '!.github/scripts/find_*'
- '!.github/scripts/on-release.sh'
- '!.github/scripts/tests_*'
- '!.github/scripts/upload_*'
concurrency:
group: build-${{github.event.pull_request.number || github.ref}}
@ -65,47 +39,41 @@ jobs:
cmake-check:
name: Check cmake file
runs-on: ubuntu-latest
if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@v4
- run: bash ./.github/scripts/check-cmakelists.sh
gen-chunks:
name: Generate chunks
runs-on: ubuntu-latest
if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) }}
outputs:
build_all: ${{ steps.set-chunks.outputs.build_all }}
build_libraries: ${{ steps.set-chunks.outputs.build_libraries }}
build_static_sketches: ${{ steps.set-chunks.outputs.build_static_sketches }}
build_idf: ${{ steps.set-chunks.outputs.build_idf }}
build_platformio: ${{ steps.set-chunks.outputs.build_platformio }}
chunk_count: ${{ steps.set-chunks.outputs.chunk_count }}
chunks: ${{ steps.set-chunks.outputs.chunks }}
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1
uses: tj-actions/changed-files@v44
with:
files_yaml: |
core:
- '.github/**'
- '!.github/scripts/install-platformio-esp32.sh'
- 'cores/**'
- 'package/**'
- 'tools/**'
- '!tools/platformio-build.py'
- 'platform.txt'
- 'programmers.txt'
- "variants/esp32/**/*"
- "variants/esp32c3/**/*"
- "variants/esp32c6/**/*"
- "variants/esp32h2/**/*"
- "variants/esp32p4/**/*"
- "variants/esp32s2/**/*"
- "variants/esp32s3/**/*"
libraries:
- 'libraries/**/examples/**'
- 'libraries/**/src/**'
@ -124,8 +92,10 @@ jobs:
idf:
- 'idf_component.yml'
- 'Kconfig.projbuild'
- 'CMakeLists.txt'
- "idf_component_examples/**"
platformio:
- 'package.json'
- '.github/scripts/install-platformio-esp32.sh'
- 'tools/platformio-build.py'
- name: Set chunks
id: set-chunks
@ -133,6 +103,7 @@ jobs:
LIB_FILES: ${{ steps.changed-files.outputs.libraries_all_changed_files }}
IS_PR: ${{ github.event_name == 'pull_request' }}
MAX_CHUNKS: ${{ env.MAX_CHUNKS }}
BUILD_PLATFORMIO: ${{ steps.changed-files.outputs.platformio_any_changed == 'true' }}
BUILD_IDF: ${{ steps.changed-files.outputs.idf_any_changed == 'true' }}
BUILD_LIBRARIES: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }}
BUILD_STATIC_SKETCHES: ${{ steps.changed-files.outputs.static_sketeches_any_changed == 'true' }}
@ -145,7 +116,7 @@ jobs:
- name: Upload sketches found
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:
name: sketches_found
path: sketches_found.txt
@ -164,13 +135,13 @@ jobs:
chunk: ${{ fromJson(needs.gen-chunks.outputs.chunks) }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.x"
python-version: '3.x'
- name: Get libs cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache@v4
with:
key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }}
path: |
@ -182,33 +153,23 @@ jobs:
./tools/riscv32-*
./tools/xtensa-*
- name: Set Log Level
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
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
if: ${{ needs.gen-chunks.outputs.build_all == 'true' }}
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ env.MAX_CHUNKS }} 1 ${{ env.LOG_LEVEL }}
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ env.MAX_CHUNKS }} 1
- name: Download sketches found
if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }}
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
uses: actions/download-artifact@v4
with:
name: sketches_found
- name: Build selected sketches
if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }}
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ needs.gen-chunks.outputs.chunk_count }} 1 ${{ env.LOG_LEVEL }} sketches_found.txt
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ needs.gen-chunks.outputs.chunk_count }} 1 sketches_found.txt
#Upload cli compile json as artifact
- name: Upload cli compile json
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@v4
with:
name: pr_cli_compile_${{ matrix.chunk }}
path: cli_compile_${{ matrix.chunk }}.json
@ -226,13 +187,35 @@ jobs:
os: [windows-latest, macOS-latest]
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.x"
python-version: '3.x'
- name: Build Sketches
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:
name: Build with ESP-IDF ${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
needs: gen-chunks
@ -240,7 +223,7 @@ jobs:
needs.gen-chunks.outputs.build_all == 'true' ||
needs.gen-chunks.outputs.build_libraries == 'true' ||
needs.gen-chunks.outputs.build_idf == 'true'
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
@ -248,43 +231,24 @@ jobs:
# 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
# for details.
idf_ver: ["release-v5.3","release-v5.4","release-v5.5"]
idf_target:
[
"esp32",
"esp32s2",
"esp32s3",
"esp32c2",
"esp32c3",
"esp32c6",
"esp32h2",
"esp32p4"
]
idf_ver: ["release-v5.1"]
idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2"]
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Check out arduino-esp32 as a component
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
with:
submodules: recursive
path: components/arduino-esp32
- name: Setup jq
uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1
- name: Build
env:
IDF_TARGET: ${{ matrix.idf_target }}
shell: bash
run: |
chmod a+x ./components/arduino-esp32/.github/scripts/*
./components/arduino-esp32/.github/scripts/on-push-idf.sh
- name: Upload generated sdkconfig files for debugging
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
. ${IDF_PATH}/export.sh
idf.py create-project test
echo CONFIG_FREERTOS_HZ=1000 > test/sdkconfig.defaults
idf.py -C test -DEXTRA_COMPONENT_DIRS=$PWD/components build
# Save artifacts to gh-pages
save-master-artifacts:
@ -295,16 +259,17 @@ jobs:
steps:
# Check out repository
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
with:
token: ${{secrets.GITHUB_TOKEN}}
fetch-depth: "0"
fetch-depth: '0'
- name: Switch branch
run: git checkout remotes/origin/gh-pages
run:
git checkout remotes/origin/gh-pages
- name: Download sketches reports artifact
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
uses: actions/download-artifact@v4
with:
pattern: pr_cli_compile_*
merge-multiple: true
@ -326,7 +291,7 @@ jobs:
#Upload PR number as artifact
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
steps:
- name: Save the PR number in an artifact
@ -334,9 +299,8 @@ jobs:
env:
PR_NUM: ${{ github.event.number }}
run: echo $PR_NUM > pr_num.txt
- name: Upload PR number
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@v4
with:
name: pr_number
path: ./pr_num.txt

View file

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

View file

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

View file

@ -5,11 +5,11 @@ on:
inputs:
type:
type: string
description: "Type of tests to build"
description: 'Type of tests to build'
required: true
chip:
type: string
description: "Chip to build tests for"
description: 'Chip to build tests for'
required: true
jobs:
@ -22,14 +22,13 @@ jobs:
- name: Check if already built
id: cache-build-binaries
if: github.event.pull_request.number != null
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache/restore@v4
with:
key: tests-${{ env.id }}-bin
path: |
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig
~/.arduino/tests/**/build*.tmp/*.bin
~/.arduino/tests/**/build*.tmp/*.elf
~/.arduino/tests/**/build*.tmp/*.json
- name: Evaluate if tests should be built
id: check-build
@ -46,10 +45,10 @@ jobs:
- name: Checkout user repository
if: ${{ steps.check-build.outputs.enabled == 'true' }}
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
- name: Get libs cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache@v4
if: ${{ steps.check-build.outputs.enabled == 'true' }}
with:
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 }}
- 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
with:
key: tests-${{ env.id }}-bin
path: |
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig
~/.arduino/tests/**/build*.tmp/*.bin
~/.arduino/tests/**/build*.tmp/*.elf
~/.arduino/tests/**/build*.tmp/*.json
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} binaries as artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@v4
with:
name: tests-bin-${{ inputs.chip }}-${{ inputs.type }}
overwrite: true
path: |
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig
~/.arduino/tests/**/build*.tmp/*.bin
~/.arduino/tests/**/build*.tmp/*.elf
~/.arduino/tests/**/build*.tmp/*.json

View file

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

View file

@ -21,7 +21,7 @@ jobs:
- name: Check if already passed
id: get-cache-results
if: github.event.pull_request.number != null
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache/restore@v4
with:
key: tests-${{ env.id }}-results-qemu
path: |
@ -43,7 +43,7 @@ jobs:
- name: Checkout user repository
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
@ -60,12 +60,12 @@ jobs:
cd .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' }}
with:
cache-dependency-path: tests/requirements.txt
cache: "pip"
python-version: "3.x"
cache: 'pip'
python-version: '3.x'
- name: Install Python dependencies
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
- 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' }}
with:
packages: libpixman-1-0 libnuma1 libglib2.0-0 libslirp0 libsdl2-2.0-0
version: 1.0
- 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' }}
id: get-qemu-version
with:
@ -92,7 +92,7 @@ jobs:
- name: Cache QEMU
id: cache-qemu
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache@v4
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
with:
path: |
@ -113,18 +113,18 @@ jobs:
- name: Get binaries
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
uses: actions/download-artifact@v4
with:
name: tests-bin-${{ inputs.chip }}-${{ inputs.type }}
path: |
~/.arduino/tests/${{ inputs.chip }}
~/.arduino/tests
- name: Run Tests
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
- 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
with:
key: tests-${{ env.id }}-results-qemu
@ -133,7 +133,7 @@ jobs:
tests/**/result_*.json
- 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()
with:
name: tests-results-qemu-${{ inputs.chip }}-${{ inputs.type }}

View file

@ -24,12 +24,12 @@ jobs:
pull-requests: write
contents: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@v4
with:
ref: gh-pages
- name: Download and Extract Artifacts
uses: dawidd6/action-download-artifact@07ab29fd4a977ae4d2b275087cf67563dfdf0295 # v9
uses: dawidd6/action-download-artifact@v6
with:
run_id: ${{ github.event.workflow_run.id }}
path: ./artifacts
@ -41,67 +41,26 @@ jobs:
original_sha=$(cat ./artifacts/parent-artifacts/sha.txt)
original_ref=$(cat ./artifacts/parent-artifacts/ref.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_action=$original_action" >> $GITHUB_ENV
echo "original_sha=$original_sha" >> $GITHUB_ENV
echo "original_ref=$original_ref" >> $GITHUB_ENV
echo "original_conclusion=$original_conclusion" >> $GITHUB_ENV
echo "original_run_id=$original_run_id" >> $GITHUB_ENV
echo "original_event = $original_event"
echo "original_action = $original_action"
echo "original_sha = $original_sha"
echo "original_ref = $original_ref"
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
uses: EnricoMi/publish-unit-test-result-action@170bf24d20d201b842d7a52403b73ed297e6645b # v2.18.0
uses: EnricoMi/publish-unit-test-result-action@v2
with:
commit: ${{ env.original_sha }}
event_file: ./artifacts/parent-artifacts/event_file/event.json
event_name: ${{ env.original_event }}
files: ./artifacts/**/*.xml
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
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
if: always()
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@v7
with:
script: |
const ref = process.env.original_ref;
const ref = '${{ env.original_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');
return;
}
@ -139,18 +98,18 @@ jobs:
});
- name: Report conclusion
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@v7
if: always()
with:
script: |
const owner = '${{ github.repository_owner }}';
const repo = '${{ github.repository }}'.split('/')[1];
const sha = process.env.original_sha;
const sha = '${{ env.original_sha }}';
core.debug(`owner: ${owner}`);
core.debug(`repo: ${repo}`);
core.debug(`sha: ${sha}`);
const { context: name, state } = (await github.rest.repos.createCommitStatus({
context: `Runtime Tests / Report results (${process.env.original_event} -> workflow_run -> workflow_run)`,
context: 'Runtime Tests / Report results (${{ env.original_event }} -> workflow_run -> workflow_run)',
owner: owner,
repo: repo,
sha: sha,
@ -160,36 +119,28 @@ jobs:
})).data;
core.info(`${name} is ${state}`);
- name: Generate report
if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled
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' }}
- name: Create output folder
if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }}
run: |
rm -rf artifacts $REPORT_FILE
mv -f ./unity_results.json ./runtime-tests-results/unity_results.json
touch $REPORT_FILE
python3 ./runtime-tests-results/table_generator.py ./runtime-tests-results/unity_results.json >> $REPORT_FILE
rm -rf artifacts
mkdir -p runtime-tests-results
- name: Generate badge
if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled
uses: jaywcjlove/generated-badges@0e078ae4d4bab3777ea4f137de496ab44688f5ad # v1.0.13
if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }}
uses: jaywcjlove/generated-badges@v1.0.13
with:
label: Runtime Tests
status: ${{ job.status == 'success' && 'passing' || 'failing' }}
status: ${{ job.status }}
output: runtime-tests-results/badge.svg
color: ${{ job.status == 'success' && 'green' || 'red' }}
style: flat
- 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: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
if [[ `git status --porcelain` ]]; then
git add --all
git commit -m "Updated runtime tests report"
git commit -m "Updated runtime tests badge"
git push origin HEAD:gh-pages
fi

View file

@ -22,12 +22,9 @@ jobs:
outputs:
pr_num: ${{ steps.set-ref.outputs.pr_num }}
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:
- name: Report pending
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@v7
with:
script: |
const owner = '${{ github.repository_owner }}';
@ -47,25 +44,17 @@ jobs:
core.info(`${name} is ${state}`);
- name: Download and extract event file
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
uses: actions/download-artifact@v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
name: 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
id: set-ref
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
pr_num=""
fi
@ -75,22 +64,11 @@ jobs:
ref=${{ github.ref }}
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
action=""
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"
printf "$ref" >> artifacts/ref.txt
@ -109,10 +87,6 @@ jobs:
printf "\nAction = "
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
echo "Failed to get PR number or ref"
exit 1
@ -124,13 +98,10 @@ jobs:
cat artifacts/conclusion.txt
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
- name: Download and extract parent hardware results
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
uses: actions/download-artifact@v4
continue-on-error: true
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
@ -140,7 +111,7 @@ jobs:
path: artifacts/results/hw
- name: Download and extract parent QEMU results
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
uses: actions/download-artifact@v4
continue-on-error: true
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
@ -150,14 +121,14 @@ jobs:
path: artifacts/results/qemu
- name: Upload parent artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@v4
with:
name: parent-artifacts
path: artifacts
if-no-files-found: error
- name: Report conclusion
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@v7
if: always()
with:
script: |
@ -193,11 +164,11 @@ jobs:
strategy:
fail-fast: false
matrix:
type: ${{ fromJson(needs.get-artifacts.outputs.types) }}
chip: ${{ fromJson(needs.get-artifacts.outputs.targets) }}
type: ['validation']
chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2']
steps:
- name: Report pending
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@v7
with:
script: |
const owner = '${{ github.repository_owner }}';
@ -219,7 +190,7 @@ jobs:
- name: Check if already passed
id: get-cache-results
if: needs.get-artifacts.outputs.pr_num
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache/restore@v4
with:
key: tests-${{ env.id }}-results-wokwi
path: |
@ -240,19 +211,16 @@ jobs:
echo "enabled=$enabled" >> $GITHUB_OUTPUT
# 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
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.get-artifacts.outputs.base || github.ref }}
uses: actions/checkout@v4
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
- uses: actions/setup-python@v5
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
with:
cache-dependency-path: tests/requirements.txt
cache: "pip"
python-version: "3.x"
cache: 'pip'
python-version: '3.x'
- name: Install dependencies
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
@ -266,17 +234,17 @@ jobs:
- name: Wokwi CI Server
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
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
uses: actions/download-artifact@v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
name: tests-bin-${{ matrix.chip }}-${{ matrix.type }}
path: |
~/.arduino/tests/${{ matrix.chip }}
~/.arduino/tests
- name: Run Tests
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 }}
- 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
with:
key: tests-${{ env.id }}-results-wokwi
@ -295,7 +263,7 @@ jobs:
tests/**/result_*.json
- 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()
with:
name: tests-results-wokwi-${{ matrix.chip }}-${{ matrix.type }}
@ -305,7 +273,7 @@ jobs:
tests/**/result_*.json
- name: Report conclusion
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@v7
if: always()
with:
script: |

View file

@ -1,38 +1,23 @@
name: Push components to https://components.espressif.com
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:
workflows: ["ESP32 Arduino Release"]
types:
- completed
permissions:
contents: read
jobs:
upload_components:
runs-on: ubuntu-latest
steps:
- name: Get the release tag
env:
head_branch: ${{ inputs.tag || github.event.workflow_run.head_branch }}
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..."
exit 1
fi
# Read and sanitize the branch/tag name
branch=$(echo "$head_branch" | tr -cd '[:alnum:]/_.-')
branch=${{ github.event.workflow_run.head_branch }}
if [[ $branch == refs/tags/* ]]; then
tag="${branch#refs/tags/}"
elif [[ $branch =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
@ -45,13 +30,12 @@ jobs:
echo "Tag: $tag"
echo "RELEASE_TAG=$tag" >> $GITHUB_ENV
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@v4
with:
ref: ${{ inputs.git_ref || env.RELEASE_TAG }}
submodules: "recursive"
- 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:
name: arduino-esp32
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:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b" # v5.0.0
rev: "v4.5.0"
hooks:
# Generic checks
- id: check-case-conflict
- id: check-symlinks
- id: debug-statements
@ -26,85 +25,46 @@ repos:
args: [--fix=lf]
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
# JSON formatting
- id: pretty-format-json
stages: [manual]
args: [--autofix]
types_or: [json]
exclude: |
(?x)(
diagram\..*\.json$|
package\.json$|
^package\/.*$
)
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: "f6446549e5e97ec9665b9b03e75b87b445857f9a" # v18.1.3
- repo: https://github.com/codespell-project/codespell
rev: "v2.3.0"
hooks:
- id: codespell
exclude: ^.*\.(svd|SVD)$
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: "v18.1.3"
hooks:
# C/C++ formatting
- id: clang-format
types_or: [c, c++]
exclude: ^.*\/build_opt\.h$
- repo: https://github.com/psf/black-pre-commit-mirror
rev: "a4920527036bb9a3f3e6055d595849d67d0da066" # 25.1.0
rev: "22.10.0"
hooks:
# Python formatting
- id: black
types_or: [python]
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
rev: "16f5f28a384f0781bebb37a08aa45e65b9526c50" # 7.2.0
rev: "7.0.0"
hooks:
# Python linting
- id: flake8
types_or: [python]
additional_dependencies:
- flake8-bugbear
- flake8-comprehensions
- flake8-simplify
- repo: https://github.com/pre-commit/mirrors-prettier
rev: "ffb6a759a979008c0e6dff86e39f4745a2d9eac4" # v3.1.0
rev: "v3.1.0"
hooks:
# YAML formatting
- id: prettier
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
rev: "dc4c47923788a413fb5677de6e3370d514aecb78" # v3.11.2
rev: "v3.0.7"
hooks:
# Sync vale styles and lint markdown and reStructuredText
- id: vale
name: vale-sync
language_version: "1.23.2"
language_version: "1.21.6"
pass_filenames: false
args: [sync]
types_or: [markdown, rst]
- id: vale
language_version: "1.23.2"
language_version: "1.21.6"
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
# idf.py build
set(min_supported_idf_version "5.3.0")
set(max_supported_idf_version "5.5.99")
set(min_supported_idf_version "5.1.0")
set(max_supported_idf_version "5.1.99")
set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}")
if ("${idf_version}" AND NOT "$ENV{ARDUINO_SKIP_IDF_VERSION_CHECK}")
@ -25,7 +25,6 @@ endif()
set(CORE_SRCS
cores/esp32/base64.cpp
cores/esp32/cbuf.cpp
cores/esp32/ColorFormat.c
cores/esp32/chip-debug-report.cpp
cores/esp32/esp32-hal-adc.c
cores/esp32/esp32-hal-bt.c
@ -33,7 +32,6 @@ set(CORE_SRCS
cores/esp32/esp32-hal-dac.c
cores/esp32/esp32-hal-gpio.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-ledc.c
cores/esp32/esp32-hal-matrix.c
@ -47,11 +45,9 @@ set(CORE_SRCS
cores/esp32/esp32-hal-timer.c
cores/esp32/esp32-hal-tinyusb.c
cores/esp32/esp32-hal-touch.c
cores/esp32/esp32-hal-touch-ng.c
cores/esp32/esp32-hal-uart.c
cores/esp32/esp32-hal-rmt.c
cores/esp32/Esp.cpp
cores/esp32/freertos_stats.cpp
cores/esp32/FunctionalInterrupt.cpp
cores/esp32/HardwareSerial.cpp
cores/esp32/HEXBuilder.cpp
@ -97,7 +93,6 @@ set(ARDUINO_ALL_LIBRARIES
HTTPUpdate
Insights
LittleFS
Matter
NetBIOS
Network
OpenThread
@ -117,10 +112,10 @@ set(ARDUINO_ALL_LIBRARIES
WiFi
WiFiProv
Wire
Zigbee
)
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)
@ -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_OpenThread_SRCS
libraries/OpenThread/src/OThread.cpp
libraries/OpenThread/src/OThreadCLI.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
libraries/PPP/src/PPP.cpp
libraries/PPP/src/ppp.c)
@ -227,16 +203,6 @@ set(ARDUINO_LIBRARY_USB_SRCS
libraries/USB/src/USBMIDI.cpp
libraries/USB/src/USBHIDMouse.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/USBHIDConsumerControl.cpp
libraries/USB/src/USBHIDSystemControl.cpp
@ -246,11 +212,7 @@ set(ARDUINO_LIBRARY_USB_SRCS
set(ARDUINO_LIBRARY_WebServer_SRCS
libraries/WebServer/src/WebServer.cpp
libraries/WebServer/src/Parsing.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)
libraries/WebServer/src/detail/mimetable.cpp)
set(ARDUINO_LIBRARY_NetworkClientSecure_SRCS
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_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
libraries/BLE/src/BLE2901.cpp
libraries/BLE/src/BLE2902.cpp
@ -362,21 +293,17 @@ endforeach()
set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ ${ARDUINO_LIBRARIES_INCLUDEDIRS})
set(srcs ${CORE_SRCS} ${ARDUINO_LIBRARIES_SRCS})
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})
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThread)
#if(CONFIG_SOC_IEEE802154_SUPPORTED) # 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)
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})
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()
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)
endif()
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA)
maybe_add_component(esp_https_ota)
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
default y
config ARDUINO_SELECTIVE_ESP_SR
bool "Enable ESP-SR"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_EEPROM
bool "Enable EEPROM"
depends on ARDUINO_SELECTIVE_COMPILATION
@ -291,11 +286,6 @@ config ARDUINO_SELECTIVE_Update
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_Zigbee
bool "Enable Zigbee"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_FS
bool "Enable FS"
depends on ARDUINO_SELECTIVE_COMPILATION
@ -368,11 +358,6 @@ config ARDUINO_SELECTIVE_HTTPClient
select ARDUINO_SELECTIVE_NetworkClientSecure
default y
config ARDUINO_SELECTIVE_Matter
bool "Enable Matter"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
default y
config ARDUINO_SELECTIVE_NetBIOS
bool "Enable NetBIOS"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
@ -414,19 +399,4 @@ config ARDUINO_SELECTIVE_SimpleBLE
depends on ARDUINO_SELECTIVE_COMPILATION
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

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)
[![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)
[![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)
### 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)
[![Discord invite](https://img.shields.io/discord/1327272229427216425?logo=discord&logoColor=white&logoSize=auto&label=Discord)](https://discord.gg/8xY6e9crwv)
### 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)
## Contents
@ -21,17 +16,9 @@
### 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/)
[![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/)
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/)
### Development Planning
@ -67,17 +54,15 @@ Here are the ESP32 series supported by the Arduino-ESP32 project:
| **SoC** | **Stable** | **Development** | **Datasheet** |
|----------|:----------:|:---------------:|:-------------------------------------------------------------------------------------------------:|
| 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-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-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]
> ESP32-C2 is also supported by Arduino-ESP32 but requires using Arduino as an ESP-IDF component or rebuilding the static libraries.
> 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
> [Lib Builder documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/lib_builder.html), respectively.
> 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
> build system. For more information, see the [Lib Builder documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/lib_builder.html).
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/task.h"
#include "freertos/semphr.h"
#include "esp32-hal.h"
#include "esp8266-compat.h"
#include "soc/gpio_reg.h"
@ -40,9 +41,6 @@
#include "binary.h"
#include "extra_attr.h"
#include "pins_arduino.h"
#include "esp32-hal.h"
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
@ -144,7 +142,7 @@
#endif
#define EXTERNAL_NUM_INTERRUPTS NUM_DIGITAL_PINS // All GPIOs
#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)
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 "HardwareSerial.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
using std::abs;
@ -251,7 +248,7 @@ void noTone(uint8_t _pin);
#endif /* __cplusplus */
// must be applied last as it overrides some of the above
#include "pins_arduino.h"
#include "io_pin_remap.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_sleep.h"
#include "spi_flash_mmap.h"
#include "esp_idf_version.h"
#include <memory>
#include <soc/soc.h>
#include <esp_partition.h>
@ -61,12 +60,6 @@ extern "C" {
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/spi_flash.h"
#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
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -281,7 +274,7 @@ const char *EspClass::getChipModel(void) {
return "ESP32-D0WD";
}
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_ESP32PICOV302: return "ESP32-PICO-V3-02";
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDR2V3: return "ESP32-D0WDR2-V3";
@ -304,12 +297,6 @@ const char *EspClass::getChipModel(void) {
case CHIP_ESP32C2: return "ESP32-C2";
case CHIP_ESP32C6: return "ESP32-C6";
case CHIP_ESP32H2: return "ESP32-H2";
case CHIP_ESP32P4: return "ESP32-P4";
#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
@ -348,8 +335,6 @@ uint32_t EspClass::getFlashChipSpeed(void) {
return magicFlashChipSpeed(fhdr.spi_speed);
}
// FIXME for P4
#if !defined(CONFIG_IDF_TARGET_ESP32P4)
FlashMode_t EspClass::getFlashChipMode(void) {
#if CONFIG_IDF_TARGET_ESP32S2
uint32_t spi_ctrl = REG_READ(PERIPHS_SPI_FLASH_CTRL);
@ -376,7 +361,6 @@ FlashMode_t EspClass::getFlashChipMode(void) {
}
return (FM_DOUT);
}
#endif // if !defined(CONFIG_IDF_TARGET_ESP32P4)
uint32_t EspClass::magicFlashChipSize(uint8_t byte) {
/*

View file

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

View file

@ -286,14 +286,14 @@ bool HWCDC::deinit(void *busptr) {
running = true;
// Setting USB D+ D- pins
bool retCode = true;
retCode &= perimanClearPinBus(USB_INT_PHY0_DM_GPIO_NUM);
retCode &= perimanClearPinBus(USB_INT_PHY0_DP_GPIO_NUM);
retCode &= perimanClearPinBus(USB_DM_GPIO_NUM);
retCode &= perimanClearPinBus(USB_DP_GPIO_NUM);
if (retCode) {
// Force the host to re-enumerate (BUS_RESET)
pinMode(USB_INT_PHY0_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN);
pinMode(USB_INT_PHY0_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN);
digitalWrite(USB_INT_PHY0_DM_GPIO_NUM, LOW);
digitalWrite(USB_INT_PHY0_DP_GPIO_NUM, LOW);
pinMode(USB_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN);
pinMode(USB_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN);
digitalWrite(USB_DM_GPIO_NUM, LOW);
digitalWrite(USB_DP_GPIO_NUM, LOW);
}
// release the flag
running = false;
@ -323,11 +323,11 @@ void HWCDC::begin(unsigned long baud) {
// delay(10); // USB Host has to enumerate it again
// 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)) {
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)) {
goto err;
}
@ -603,7 +603,6 @@ void HWCDC::setDebugOutput(bool en) {
} else {
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

View file

@ -20,7 +20,6 @@
#include <inttypes.h>
#include "Stream.h"
#include <functional>
class HardwareI2C : public Stream {
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) = 0;
// Update base class to use std::function
virtual void onReceive(const std::function<void(int)> &) = 0;
virtual void onRequest(const std::function<void()> &) = 0;
virtual void onReceive(void (*)(int)) = 0;
virtual void onRequest(void (*)(void)) = 0;
};

View file

@ -11,34 +11,31 @@
#include "driver/uart.h"
#include "freertos/queue.h"
#if (SOC_UART_LP_NUM >= 1)
#define UART_HW_FIFO_LEN(uart_num) ((uart_num < SOC_UART_HP_NUM) ? SOC_UART_FIFO_LEN : SOC_LP_UART_FIFO_LEN)
#else
#define UART_HW_FIFO_LEN(uart_num) SOC_UART_FIFO_LEN
#ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048
#endif
#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
void serialEvent(void) __attribute__((weak));
void serialEvent(void) {}
#if SOC_UART_NUM > 1
void serialEvent1(void) __attribute__((weak));
void serialEvent1(void) {}
#endif /* SOC_UART_NUM > 1 */
#if SOC_UART_NUM > 2
void serialEvent2(void) __attribute__((weak));
void serialEvent2(void) {}
#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)
// There is always Seria0 for UART0
HardwareSerial Serial0(0);
@ -48,64 +45,43 @@ HardwareSerial Serial1(1);
#if SOC_UART_NUM > 2
HardwareSerial Serial2(2);
#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
extern void HWCDCSerialEvent(void) __attribute__((weak));
void HWCDCSerialEvent(void) {}
#endif
#if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event
// Used by Hardware Serial for USB CDC events
extern void USBSerialEvent(void) __attribute__((weak));
void USBSerialEvent(void) {}
#endif
void serialEventRun(void) {
#if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event
if (HWCDCSerialEvent && HWCDCSerial.available()) {
if (HWCDCSerial.available()) {
HWCDCSerialEvent();
}
#endif
#if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event
if (USBSerialEvent && USBSerial.available()) {
if (USBSerial.available()) {
USBSerialEvent();
}
#endif
// UART0 is default serialEvent()
if (serialEvent && Serial0.available()) {
if (Serial0.available()) {
serialEvent();
}
#if SOC_UART_NUM > 1
if (serialEvent1 && Serial1.available()) {
if (Serial1.available()) {
serialEvent1();
}
#endif
#if SOC_UART_NUM > 2
if (serialEvent2 && Serial2.available()) {
if (Serial2.available()) {
serialEvent2();
}
#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
@ -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
// 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 && _uart_nr < SOC_UART_HP_NUM) {
if (_onReceiveTimeout) {
uartSetRxFIFOFull(_uart, 120);
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();
// 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)
// Not valid for the LP UART
if (_onReceiveCB != NULL && _onReceiveTimeout && _uart_nr < SOC_UART_HP_NUM) {
if (_onReceiveCB != NULL && _onReceiveTimeout) {
fifoBytes = 120;
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
}
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;
}
HSERIAL_MUTEX_UNLOCK();
@ -317,15 +291,6 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
}
#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();
// First Time or after end() --> set default Pins
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;
}
break;
#if SOC_UART_HP_NUM > 1
#if SOC_UART_NUM > 1 // may save some flash bytes...
case UART_NUM_1:
if (rxPin < 0 && txPin < 0) {
// 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;
}
break;
#endif // UART_NUM_1
#if SOC_UART_HP_NUM > 2
#endif
#if SOC_UART_NUM > 2 // may save some flash bytes...
case UART_NUM_2:
if (rxPin < 0 && txPin < 0) {
// do not change RX2/TX2 if it has already been set before
#ifdef RX2
rxPin = _rxPin < 0 ? (int8_t)RX2 : _rxPin;
#endif
#ifdef TX2
txPin = _txPin < 0 ? (int8_t)TX2 : _txPin;
#endif
}
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
#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
if (rxPin < 0 && txPin < 0) {
log_e("No RX/TX pins defined. Please set RX/TX pins.");
HSERIAL_MUTEX_UNLOCK();
return;
}
// map logical pins to GPIO numbers
rxPin = digitalPinToGPIONumber(rxPin);
txPin = digitalPinToGPIONumber(txPin);
// IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified.
// 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()
// set a default FIFO Full value for the IDF driver
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 (_uart_nr < SOC_UART_HP_NUM && (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout))) {
if (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout)) {
fifoFull = 120;
}
uartSetRxFIFOFull(_uart, fifoFull);
@ -498,12 +415,6 @@ void HardwareSerial::setDebugOutput(bool en) {
if (_uart == 0) {
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) {
uartSetDebug(_uart);
} else {
@ -607,56 +518,35 @@ bool HardwareSerial::setMode(SerialMode 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.
// LP UART has FIFO of 16 bytes
size_t HardwareSerial::setRxBufferSize(size_t new_size) {
if (_uart) {
log_e("RX Buffer can't be resized when Serial is already running. Set it before calling begin().");
return 0;
}
uint8_t FIFOLen = UART_HW_FIFO_LEN(_uart_nr);
// Valid value is higher than the FIFO length
if (new_size <= FIFOLen) {
new_size = FIFOLen + 1;
log_w("RX Buffer set to minimum value: %d.", new_size);
if (new_size <= SOC_UART_FIFO_LEN) {
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 = SOC_UART_FIFO_LEN + 1;
}
_rxBufferSize = new_size;
return _rxBufferSize;
}
// minimum total TX Buffer size is the UART FIFO space (128 bytes for most SoC) + 1.
// LP UART has FIFO of 16 bytes
// minimum total TX Buffer size is the UART FIFO space (128 bytes for most SoC).
size_t HardwareSerial::setTxBufferSize(size_t new_size) {
if (_uart) {
log_e("TX Buffer can't be resized when Serial is already running. Set it before calling begin().");
return 0;
}
uint8_t FIFOLen = UART_HW_FIFO_LEN(_uart_nr);
// Valid values are zero or higher than the FIFO length
if (new_size > 0 && new_size <= FIFOLen) {
new_size = FIFOLen + 1;
log_w("TX Buffer set to minimum value: %d.", new_size);
if (new_size <= SOC_UART_FIFO_LEN) {
log_w("TX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN); // ESP32, S2, S3 and C3 means higher than 128
_txBufferSize = 0; // it will use just UART FIFO with SOC_UART_FIFO_LEN bytes (128 for most SoC)
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()"
_txBufferSize = new_size;

View file

@ -96,51 +96,16 @@ typedef enum {
UART_PARITY_ERROR
} 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 CONFIG_ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
#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
#ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY
#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_PRIORITY
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES - 1)
#else
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY CONFIG_ARDUINO_SERIAL_EVENT_TASK_PRIORITY
#endif
#endif
#ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
#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
// UART0 pins are defined by default by the bootloader.
@ -160,10 +125,6 @@ typedef enum {
#define SOC_RX0 (gpio_num_t)17
#elif CONFIG_IDF_TARGET_ESP32H2
#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
@ -180,16 +141,12 @@ typedef enum {
#define SOC_TX0 (gpio_num_t)16
#elif CONFIG_IDF_TARGET_ESP32H2
#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
// Default pins for UART1 are arbitrary, and defined here for convenience.
#if SOC_UART_HP_NUM > 1
#if SOC_UART_NUM > 1
#ifndef RX1
#if CONFIG_IDF_TARGET_ESP32
#define RX1 (gpio_num_t)26
@ -205,10 +162,6 @@ typedef enum {
#define RX1 (gpio_num_t)4
#elif CONFIG_IDF_TARGET_ESP32H2
#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
@ -227,17 +180,13 @@ typedef enum {
#define TX1 (gpio_num_t)5
#elif CONFIG_IDF_TARGET_ESP32H2
#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 /* SOC_UART_HP_NUM > 1 */
#endif /* SOC_UART_NUM > 1 */
// Default pins for UART2 are arbitrary, and defined here for convenience.
#if SOC_UART_HP_NUM > 2
#if SOC_UART_NUM > 2
#ifndef RX2
#if CONFIG_IDF_TARGET_ESP32
#define RX2 (gpio_num_t)4
@ -253,17 +202,7 @@ typedef enum {
#define TX2 (gpio_num_t)20
#endif
#endif
#endif /* SOC_UART_HP_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 */
#endif /* SOC_UART_NUM > 2 */
typedef std::function<void(void)> OnReceiveCb;
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)
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,
uint8_t rxfifo_full_thrhd = 120
uint8_t rxfifo_full_thrhd = 112
);
void end(void);
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_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes)
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 setTxBufferSize(size_t new_size);
@ -435,15 +363,6 @@ extern HardwareSerial Serial1;
#if SOC_UART_NUM > 2
extern HardwareSerial Serial2;
#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 // HardwareSerial_h

View file

@ -22,10 +22,6 @@
#include "lwip/netif.h"
#include "StreamString.h"
#ifndef CONFIG_LWIP_IPV6
#define IP6_NO_ZONE 0
#endif
IPAddress::IPAddress() : IPAddress(IPv4) {}
IPAddress::IPAddress(IPType ip_type) {
@ -205,13 +201,7 @@ bool IPAddress::fromString6(const char *address) {
colons++;
acc = 0;
} else if (c == '%') {
// netif_index_to_name crashes on latest esp-idf
// _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'
_zone = netif_name_to_index(address);
while (*address != '\0') {
address++;
}
@ -354,25 +344,12 @@ size_t IPAddress::printTo(Print &p, bool includeZone) const {
n += p.print(':');
}
}
// add a zone if zone-id is non-zero (causes exception on recent IDF builds)
// 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
// add a zone if zone-id is non-zero
if (_zone > 0 && includeZone) {
n += p.print('%');
// look for the interface name
for (netif *intf = netif_list; intf != nullptr; intf = intf->next) {
if (_zone - 1 == intf->num) {
n += p.print(intf->name[0]);
n += p.print(intf->name[1]);
break;
}
}
n += p.print(_zone - 1);
char if_name[NETIF_NAMESIZE];
netif_index_to_name(_zone, if_name);
n += p.print(if_name);
}
return n;
}
@ -391,7 +368,6 @@ IPAddress::IPAddress(const ip_addr_t *addr) {
}
void IPAddress::to_ip_addr_t(ip_addr_t *addr) const {
#if CONFIG_LWIP_IPV6
if (_type == IPv6) {
addr->type = IPADDR_TYPE_V6;
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->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) {
#if CONFIG_LWIP_IPV6
if (addr->type == IPADDR_TYPE_V6) {
_type = IPv6;
_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;
#endif /* LWIP_IPV6_SCOPES */
} else {
#endif
_type = IPv4;
memset(_address.bytes, 0, sizeof(_address.bytes));
#if CONFIG_LWIP_IPV6
_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;
}
#if CONFIG_LWIP_IPV6
esp_ip6_addr_type_t IPAddress::addr_type() const {
if (_type != IPv6) {
return ESP_IP6_ADDR_IS_UNKNOWN;
@ -445,9 +409,6 @@ esp_ip6_addr_type_t IPAddress::addr_type() const {
to_ip_addr_t(&addr);
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);
#endif
const IPAddress INADDR_NONE(0, 0, 0, 0);

View file

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

View file

@ -18,14 +18,14 @@
Created July 2011
parsing functions based on TextFinder library by Michael Margolis
findMulti/findUntil routines written by Jim Leonard/Xuth
*/
#include "Arduino.h"
#include "Stream.h"
#include "esp32-hal.h"
#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
int Stream::timedRead() {
@ -55,26 +55,18 @@ int Stream::timedPeek() {
// returns peek of the next digit in the stream or -1 if timeout
// discards non-numeric characters
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) {
int Stream::peekNextDigit() {
int c;
while (1) {
c = timedPeek();
if (c < 0 || c == '-' || (c >= '0' && c <= '9') || (detectDecimal && c == '.')) {
if (c < 0) {
return c; // timeout
}
if (c == '-') {
return c;
}
switch (lookahead) {
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;
if (c >= '0' && c <= '9') {
return c;
}
read(); // discard non-numeric
}
@ -87,6 +79,9 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
{
_timeout = timeout;
}
unsigned long Stream::getTimeout(void) {
return _timeout;
}
// find returns true if the target string is found
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) {
if (terminator == NULL) {
MultiTarget t[1] = {{target, targetLen, 0}};
return findMulti(t, 1) == 0;
return findMulti(t, 1) == 0 ? true : false;
} else {
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) {
// any zero length target string automatically matches and would make
// 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) {
// 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) {
return t - targets;
} else {
@ -283,7 +149,7 @@ int Stream::findMulti(struct Stream::MultiTarget *targets, int tCount) {
do {
--t->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;
}
@ -316,3 +182,146 @@ int Stream::findMulti(struct Stream::MultiTarget *targets, int tCount) {
// unreachable
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

@ -19,7 +19,8 @@
parsing functions based on TextFinder library by Michael Margolis
*/
#pragma once
#ifndef Stream_h
#define Stream_h
#include <inttypes.h>
#include "Print.h"
@ -27,57 +28,45 @@
// compatibility macros for testing
/*
#define getInt() parseInt()
#define getInt(ignore) parseInt(ignore)
#define getInt(skipChar) parseInt(skipchar)
#define getFloat() parseFloat()
#define getFloat(ignore) parseFloat(ignore)
#define getFloat(skipChar) parseFloat(skipChar)
#define getString( pre_string, post_string, 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 {
protected:
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
unsigned long _startMillis; // used for timeout measurement
int timedRead(); // private method to read 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:
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
Stream() {
Stream() : _startMillis(0) {
_timeout = 1000;
}
virtual ~Stream() {}
// parsing methods
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
unsigned long getTimeout(void) {
return _timeout;
}
unsigned long getTimeout(void);
bool find(const char *target); // reads data from the stream until the target string is found
bool find(const uint8_t *target) {
return find((const char *)target);
bool find(uint8_t *target) {
return find((char *)target);
}
// 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 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
@ -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 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 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);
// 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 parseInt(); // returns the first valid (long) integer value from the current position.
// initial characters that are not digits (or the minus sign) are skipped
// integer is terminated by the first character that is not a digit.
float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
// float version of parseInt
float parseFloat(); // float version of parseInt
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) {
@ -124,15 +109,11 @@ public:
String readStringUntil(char terminator);
protected:
long parseInt(char ignore) {
return parseInt(SKIP_ALL, ignore);
}
float parseFloat(char ignore) {
return parseFloat(SKIP_ALL, ignore);
}
// 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.
long parseInt(char skipChar); // as above but the given skipChar is ignored
// as above but the given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored
float parseFloat(char skipChar); // as above but the given skipChar is ignored
struct MultiTarget {
const char *str; // string you're searching for
@ -145,4 +126,4 @@ protected:
int findMulti(struct MultiTarget *targets, int tCount);
};
#undef NO_IGNORE_CHAR
#endif

View file

@ -4,11 +4,9 @@
#include "freertos/queue.h"
#include "freertos/semphr.h"
#if SOC_LEDC_SUPPORTED
static TaskHandle_t _tone_task = NULL;
static QueueHandle_t _tone_queue = NULL;
static int8_t _pin = -1;
static uint8_t _channel = 255;
typedef enum {
TONE_START,
@ -22,12 +20,6 @@ typedef struct {
unsigned long duration;
} 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 *) {
tone_msg_t tone_msg;
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);
if (_pin == -1) {
bool ret = true;
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) {
if (ledcAttach(tone_msg.pin, tone_msg.frequency, 10) == 0) {
log_e("Tone start failed");
break;
}
@ -87,7 +73,7 @@ static int tone_init() {
"toneTask", // Name of the task
3500, // Stack size in words
NULL, // Task input parameter
10, // Priority of the task must be higher than Arduino task
1, // Priority of the task
&_tone_task // Task handle.
);
if (_tone_task == NULL) {
@ -140,13 +126,3 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
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) {
tinyusb_device_mounted = true;
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);
}
@ -108,7 +107,6 @@ void tud_mount_cb(void) {
void tud_umount_cb(void) {
tinyusb_device_mounted = false;
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);
}
@ -125,7 +123,6 @@ void tud_suspend_cb(bool remote_wakeup_en) {
void tud_resume_cb(void) {
tinyusb_device_suspended = false;
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);
}

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_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) {
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.
TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, CFG_TUD_ENDOINT_SIZE, 0x03, 0x84, CFG_TUD_ENDOINT_SIZE)
};
*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)
TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, 64, 0x03, 0x84, 64)
};
*itf += 2;
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
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 < CFG_TUD_CDC && devices[itf] != NULL) {
if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) {
devices[itf]->_onLineState(dtr, rts);
}
}
// 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) {
//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 < CFG_TUD_CDC && devices[itf] != NULL) {
if (itf < MAX_USB_CDC_DEVICES && 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);
}
}
// Invoked when received new data
void tud_cdc_rx_cb(uint8_t itf) {
//log_v("ITF: %u", itf);
if (itf < CFG_TUD_CDC && devices[itf] != NULL) {
if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) {
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
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();
}
}
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);
}
}
@ -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)
: 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) {
if (itf < CFG_TUD_CDC) {
if (itf == 0) {
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);
}
if (itf < MAX_USB_CDC_DEVICES) {
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) {
if (itf >= CFG_TUD_CDC) {
return;
}
if (tx_lock == NULL) {
tx_lock = xSemaphoreCreateMutex();
}
@ -181,9 +153,6 @@ void USBCDC::begin(unsigned long baud) {
}
void USBCDC::end() {
if (itf >= CFG_TUD_CDC) {
return;
}
connected = false;
devices[itf] = NULL;
setRxBufferSize(0);
@ -329,14 +298,14 @@ bool USBCDC::rebootEnabled(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 uxQueueMessagesWaiting(rx_queue);
}
int USBCDC::peek(void) {
if (itf >= CFG_TUD_CDC || rx_queue == NULL) {
if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) {
return -1;
}
uint8_t c;
@ -347,7 +316,7 @@ int USBCDC::peek(void) {
}
int USBCDC::read(void) {
if (itf >= CFG_TUD_CDC || rx_queue == NULL) {
if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) {
return -1;
}
uint8_t c = 0;
@ -358,7 +327,7 @@ int USBCDC::read(void) {
}
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;
}
uint8_t c = 0;
@ -370,7 +339,7 @@ size_t USBCDC::read(uint8_t *buffer, size_t size) {
}
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;
}
if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) {
@ -381,7 +350,7 @@ void USBCDC::flush(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;
}
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) {
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;
}
if (xPortInIsrContext()) {
@ -446,20 +415,16 @@ uint32_t USBCDC::baudRate() {
}
void USBCDC::setDebugOutput(bool en) {
if (itf) {
return;
}
if (en) {
uartSetDebug(NULL);
ets_install_putc2((void (*)(char)) & cdc0_write_char);
} else {
ets_install_putc2(NULL);
}
ets_install_putc1(NULL); // closes UART log output
}
USBCDC::operator bool() const {
if (itf >= CFG_TUD_CDC) {
if (itf >= MAX_USB_CDC_DEVICES) {
return false;
}
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();
TU_VERIFY(ep_num != 0);
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;
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 (isSSO() || !buffer()) {
// Already using SSO, nothing to do
size_t oldLen = len();
uint16_t oldLen = len();
setSSO(true);
setLen(oldLen);
} else { // if bufptr && !isSSO()
@ -188,7 +188,7 @@ bool String::changeBuffer(unsigned int maxStrLen) {
char temp[sizeof(sso.buff)];
memcpy(temp, buffer(), maxStrLen);
free(wbuffer());
size_t oldLen = len();
uint16_t oldLen = len();
setSSO(true);
memcpy(wbuffer(), temp, maxStrLen);
setLen(oldLen);
@ -201,7 +201,7 @@ bool String::changeBuffer(unsigned int maxStrLen) {
if (newSize > CAPACITY_MAX) {
return false;
}
size_t oldLen = len();
uint16_t oldLen = len();
char *newbuffer = (char *)realloc(isSSO() ? nullptr : wbuffer(), newSize);
if (newbuffer) {
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) {
if (cstr == nullptr || !reserve(length)) {
if (!reserve(length)) {
invalidate();
return *this;
}
memmove(wbuffer(), cstr, length);
memmove(wbuffer(), cstr, length + 1);
setLen(length);
return *this;
}
@ -239,20 +239,17 @@ String &String::copy(const char *cstr, unsigned int length) {
void String::move(String &rhs) {
if (buffer()) {
if (capacity() >= rhs.len()) {
// Use case: When 'reserve()' was called and the first
// assignment/append is the return value of a function.
if (rhs.len() && rhs.buffer()) {
memmove(wbuffer(), rhs.buffer(), rhs.length());
}
memmove(wbuffer(), rhs.buffer(), rhs.length() + 1);
setLen(rhs.len());
rhs.invalidate();
return;
}
} else {
if (!isSSO()) {
free(wbuffer());
setBuffer(nullptr);
}
}
}
if (rhs.isSSO()) {
setSSO(true);
memmove(sso.buff, rhs.sso.buff, sizeof(sso.buff));
@ -262,7 +259,10 @@ void String::move(String &rhs) {
}
setCapacity(rhs.capacity());
setLen(rhs.len());
rhs.init();
rhs.setSSO(false);
rhs.setCapacity(0);
rhs.setBuffer(nullptr);
rhs.setLen(0);
}
#endif
@ -270,7 +270,12 @@ String &String::operator=(const String &rhs) {
if (this == &rhs) {
return *this;
}
return copy(rhs.buffer(), rhs.len());
if (rhs.buffer()) {
copy(rhs.buffer(), rhs.len());
} else {
invalidate();
}
return *this;
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
@ -290,8 +295,12 @@ String &String::operator=(StringSumHelper &&rval) {
#endif
String &String::operator=(const char *cstr) {
const uint32_t length = cstr ? strlen(cstr) : 0u;
return copy(cstr, length);
if (cstr) {
copy(cstr, strlen(cstr));
} else {
invalidate();
}
return *this;
}
/*********************************************/
@ -302,22 +311,24 @@ bool String::concat(const String &s) {
// 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
if (&s == this) {
if (s.len() == 0) {
return true;
}
unsigned int newlen = 2 * len();
if (!s.buffer()) {
return false;
}
unsigned int newlen = 2 * len();
if (s.len() == 0) {
return true;
}
if (!reserve(newlen)) {
return false;
}
memmove(wbuffer() + len(), buffer(), len());
setLen(newlen);
wbuffer()[len()] = 0;
return true;
}
} else {
return concat(s.buffer(), s.len());
}
}
bool String::concat(const char *cstr, unsigned int length) {
unsigned int newlen = len() + length;
@ -332,10 +343,10 @@ bool String::concat(const char *cstr, unsigned int length) {
}
if (cstr >= wbuffer() && cstr < wbuffer() + len()) {
// compatible with SSO in ram #6155 (case "x += x.c_str()")
memmove(wbuffer() + len(), cstr, length);
memmove(wbuffer() + len(), cstr, length + 1);
} else {
// compatible with source in flash #6367
memcpy_P(wbuffer() + len(), cstr, length);
memcpy_P(wbuffer() + len(), cstr, length + 1);
}
setLen(newlen);
return true;

View file

@ -64,13 +64,6 @@ static void printPkgVersion(void) {
#elif CONFIG_IDF_TARGET_ESP32H2
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SYS_4_REG, EFUSE_PKG_VERSION);
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
chip_report_printf("Unknown");
#endif
@ -91,16 +84,15 @@ static void printChipInfo(void) {
case CHIP_ESP32C3: chip_report_printf("ESP32-C3\n"); break;
case CHIP_ESP32C6: chip_report_printf("ESP32-C6\n"); break;
case CHIP_ESP32H2: chip_report_printf("ESP32-H2\n"); break;
case CHIP_ESP32P4: chip_report_printf("ESP32-P4\n"); 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();
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);
rtc_cpu_freq_config_t conf;
rtc_clk_cpu_freq_get_config(&conf);
@ -118,8 +110,6 @@ static void printChipInfo(void) {
static void printFlashInfo(void) {
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
#define ESP_FLASH_IMAGE_BASE 0x1000
#elif CONFIG_IDF_TARGET_ESP32P4
#define ESP_FLASH_IMAGE_BASE 0x2000
#else
#define ESP_FLASH_IMAGE_BASE 0x0000
#endif

View file

@ -75,7 +75,7 @@ static bool adcDetachBus(void *pin) {
if (err != ESP_OK) {
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);
if (err != ESP_OK) {
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);
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);
err = adc_cali_delete_scheme_line_fitting(adc_handle[adc_unit].adc_cali_handle);
if (err != ESP_OK) {
@ -310,7 +310,7 @@ uint32_t __analogReadMilliVolts(uint8_t pin) {
.bitwidth = __analogWidth,
};
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 = {
.unit_id = adc_unit,
.bitwidth = __analogWidth,
@ -379,7 +379,7 @@ static bool adcContinuousDetachBus(void *adc_unit_number) {
if (err != ESP_OK) {
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);
if (err != ESP_OK) {
return false;
@ -552,7 +552,7 @@ bool analogContinuous(const uint8_t pins[], size_t pins_count, uint32_t conversi
.bitwidth = __adcContinuousWidth,
};
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 = {
.unit_id = adc_unit,
.bitwidth = __adcContinuousWidth,

View file

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

View file

@ -19,27 +19,24 @@
#include "esp_attr.h"
#include "esp_log.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) \
&& !defined(CONFIG_IDF_TARGET_ESP32C5)
#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
#include "soc/rtc_cntl_reg.h"
#include "soc/syscon_reg.h"
#include "soc/apb_ctrl_reg.h"
#endif
#include "soc/efuse_reg.h"
#include "esp32-hal.h"
#include "esp32-hal-cpu.h"
#include "hal/timer_ll.h"
#include "esp_private/systimer.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "xtensa_timer.h"
#include "freertos/xtensa_timer.h"
#include "esp32/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "xtensa_timer.h"
#include "freertos/xtensa_timer.h"
#include "esp32s2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "xtensa_timer.h"
#include "freertos/xtensa_timer.h"
#include "esp32s3/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C2
#include "esp32c2/rom/rtc.h"
@ -49,10 +46,6 @@
#include "esp32c6/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#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
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -168,25 +161,23 @@ bool removeApbChangeCallback(void *arg, apb_change_cb_t cb) {
}
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) {
return 80 * MHZ;
}
return (conf->source_freq_mhz * MHZ) / conf->div;
#else
return APB_CLK_FREQ;
#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
#endif
bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
rtc_cpu_freq_config_t conf, cconf;
uint32_t capb, apb;
//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();
#endif
#if CONFIG_IDF_TARGET_ESP32
@ -202,7 +193,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
}
}
#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 (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);
@ -244,7 +235,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
}
//Make the frequency change
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) {
//Update REF_TICK (uncomment if REF_TICK is different than 1MHz)
//if(conf.freq_mhz < 80){
@ -253,18 +244,15 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
//Update APB Freq REG
rtc_clk_apb_freq_update(apb);
//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);
#endif
#endif
}
#endif
//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);
_xt_tick_divisor = fcpu / XT_TICK_PER_SEC;
#endif
@ -272,21 +260,16 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
if (apb_change_callbacks) {
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(
"%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_freq_mhz, conf.div, conf.freq_mhz, apb
);
#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 == RTC_CPU_FREQ_SRC_PLL) ? "PLL"
: ((conf.source == RTC_CPU_FREQ_SRC_APLL) ? "APLL" : ((conf.source == RTC_CPU_FREQ_SRC_XTAL) ? "XTAL" : "8M")),
conf.source_freq_mhz, conf.div, conf.freq_mhz, apb
);
#else
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
);
#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) {
gpio_set_level((gpio_num_t)pin, val);
} 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) {
return RGB_BUILTIN_storage;
}
#endif // RGB_BUILTIN
// 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) {
log_w("IO %i is not set as GPIO. digitalRead() may return an inconsistent value.", pin);
}
#endif
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) {
return gpio_get_level((gpio_num_t)pin);
} else {
log_e("IO %i is not set as GPIO.", pin);
return 0;
}
}
static void ARDUINO_ISR_ATTR __onPinInterrupt(void *arg) {

View file

@ -24,9 +24,9 @@
extern "C" {
#endif
#include "pins_arduino.h"
#include "esp32-hal.h"
#include "soc/soc_caps.h"
#include "pins_arduino.h"
#include "driver/gpio.h"
#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 "soc/i2c_reg.h"
#include "soc/i2c_struct.h"
#include "soc/periph_defs.h"
#include "hal/i2c_ll.h"
#include "hal/i2c_types.h"
#ifndef CONFIG_IDF_TARGET_ESP32C5
#include "hal/clk_gate_ll.h"
#endif
#include "esp32-hal-log.h"
#include "esp32-hal-i2c-slave.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
#ifdef CONFIG_IDF_TARGET_ESP32P4
#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
#if SOC_I2C_NUM > 1
#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))
#else
#define I2C_SCL_IDX(p) I2CEXT0_SCL_OUT_IDX
#define I2C_SDA_IDX(p) I2CEXT0_SDA_OUT_IDX
#endif
#endif // ifdef CONFIG_IDF_TARGET_ESP32P4
#if CONFIG_IDF_TARGET_ESP32
#define I2C_TXFIFO_WM_INT_ENA I2C_TXFIFO_EMPTY_INT_ENA
@ -121,14 +99,14 @@ typedef union {
uint32_t val;
} 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
#if !CONFIG_DISABLE_HAL_LOCKS
,
NULL
#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
#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) {
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
return hw->status_reg.slave_addressed;
#else
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
return hw->sr.slave_addressed;
#else
return hw->status_reg.slave_addressed;
#endif
}
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
return hw->status_reg.slave_rw;
#else
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
return hw->sr.slave_rw;
#else
return hw->status_reg.slave_rw;
#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) {
if (num >= SOC_HP_I2C_NUM) {
if (num >= SOC_I2C_NUM) {
log_e("Invalid port num: %u", num);
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) {
if (num >= SOC_HP_I2C_NUM) {
if (num >= SOC_I2C_NUM) {
log_e("Invalid port num: %u", num);
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 = (frequency * 5) / 4;
#if !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(CONFIG_IDF_TARGET_ESP32C5)
if (i2c->num == 0) {
periph_ll_enable_clk_clear_rst(PERIPH_I2C0_MODULE);
#if SOC_HP_I2C_NUM > 1
#if SOC_I2C_NUM > 1
} else {
periph_ll_enable_clk_clear_rst(PERIPH_I2C1_MODULE);
#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_set_fifo_mode(i2c->dev, true);
#endif
i2c_ll_set_fifo_mode(i2c->dev, true);
i2c_ll_set_slave_addr(i2c->dev, slaveID, false);
i2c_ll_set_tout(i2c->dev, I2C_LL_MAX_TIMEOUT);
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_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
#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
i2c_ll_set_fifo_mode(i2c->dev, true);
if (!i2c->intr_handle) {
uint32_t flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED;
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);
#else
ret = esp_intr_alloc(ETS_I2C0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle);
#endif
#if SOC_HP_I2C_NUM > 1
#if SOC_I2C_NUM > 1
} 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);
#else
ret = esp_intr_alloc(ETS_I2C1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle);
#endif
#endif
}
@ -421,7 +375,7 @@ fail:
}
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);
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) {
if (num >= SOC_HP_I2C_NUM) {
if (num >= SOC_I2C_NUM) {
log_e("Invalid port num: %u", num);
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;
#if SOC_I2C_SUPPORT_APB
i2c_ll_master_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal);
I2C_CLOCK_SRC_ATOMIC() {
i2c_ll_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal);
i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/
}
#elif SOC_I2C_SUPPORT_XTAL
#ifndef XTAL_CLK_FREQ
#define XTAL_CLK_FREQ APB_CLK_FREQ
#endif
i2c_ll_master_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal);
I2C_CLOCK_SRC_ATOMIC() {
i2c_ll_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal);
i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_XTAL); /*!< I2C source clock from XTAL, 40M */
}
#endif
i2c_ll_set_txfifo_empty_thr(i2c->dev, 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_master_set_filter(i2c->dev, 3);
i2c_ll_set_bus_timing(i2c->dev, &clk_cal);
i2c_ll_set_filter(i2c->dev, 3);
return true;
}

View file

@ -15,8 +15,6 @@
#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"
@ -31,19 +29,6 @@
#include "hal/i2c_ll.h"
#include "driver/i2c.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
#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 ret = ESP_OK;
if (i2c_num >= SOC_I2C_NUM) {
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
if (bus[i2c_num].initialized) {
log_e("bus is already initialized");
ret = ESP_FAIL;
goto init_fail;
return ESP_FAIL;
}
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);
if (!perimanClearPinBus(sda) || !perimanClearPinBus(scl)) {
ret = ESP_FAIL;
goto init_fail;
return false;
}
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.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) {
log_e("i2c_param_config failed");
} 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);
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;
return false;
}
}
}
init_fail:
#if !CONFIG_DISABLE_HAL_LOCKS
//release 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();
}
#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);
}
bus[i2c_num].frequency = frequency;
//Clock Stretching Timeout: 20b:esp32, 5b:esp32-c3, 24b:esp32-s2
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;
}
#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0) */
#endif /* SOC_I2C_SUPPORTED */

View file

@ -19,7 +19,6 @@
#include "soc/soc_caps.h"
#if SOC_I2C_SUPPORTED
#include "esp_idf_version.h"
#ifdef __cplusplus
extern "C" {
@ -40,10 +39,6 @@ esp_err_t i2cWriteReadNonStop(
);
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
}
#endif

View file

@ -22,9 +22,6 @@
#include "soc/gpio_sig_map.h"
#include "esp_rom_gpio.h"
#include "hal/ledc_ll.h"
#if SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
#include <math.h>
#endif
#ifdef SOC_LEDC_SUPPORT_HS_MODE
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM << 1)
@ -48,96 +45,6 @@ typedef struct {
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 ledc_clk_cfg_t clock_source = LEDC_DEFAULT_CLK;
@ -174,8 +81,6 @@ static bool ledcDetachBus(void *bus) {
}
pinMatrixOutDetach(handle->pin, false, false);
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);
}
free(handle);
@ -212,59 +117,32 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c
return false;
}
uint8_t group = (channel / SOC_LEDC_CHANNEL_NUM);
uint8_t timer = 0;
uint8_t group = (channel / 8), timer = ((channel / 2) % 4);
bool channel_used = ledc_handle.used_channels & (1UL << channel);
if (channel_used) {
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!");
return false;
}
} else {
// Find a timer with matching frequency and resolution, or a free timer
if (!find_matching_timer(group, freq, resolution, &timer)) {
if (!find_free_timer(group, &timer)) {
log_w("No free timers available for speed mode %u", group);
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;
ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = resolution, .freq_hz = freq, .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));
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;
uint32_t duty = ledc_get_duty(group, (channel % 8));
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_handle_t *handle = (ledc_channel_handle_t *)malloc(sizeof(ledc_channel_handle_t));
handle->pin = pin;
handle->channel = channel;
handle->timer_num = timer;
handle->freq_hz = freq;
#ifndef SOC_LEDC_SUPPORT_FADE_STOP
handle->lock = NULL;
#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;
}
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);
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
// Try the first available 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;
return ledcAttachChannel(pin, freq, resolution, channel);
}
bool ledcWrite(uint8_t pin, uint32_t duty) {
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
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
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;
}
if (ledc_set_duty(group, channel, duty) != ESP_OK) {
log_e("ledc_set_duty failed");
return false;
}
if (ledc_update_duty(group, channel) != ESP_OK) {
log_e("ledc_update_duty failed");
return false;
}
ledc_set_duty(group, channel, duty);
ledc_update_duty(group, channel);
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);
return false;
}
uint8_t group = (channel / SOC_LEDC_CHANNEL_NUM);
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);
uint8_t group = (channel / 8), timer = ((channel / 2) % 4);
//Fixing if all bits in resolution is set = LEDC FULL ON
uint32_t resolution = 0;
@ -375,14 +217,8 @@ bool ledcWriteChannel(uint8_t channel, uint32_t duty) {
duty = max_duty + 1;
}
if (ledc_set_duty(group, channel, duty) != ESP_OK) {
log_e("ledc_set_duty failed");
return false;
}
if (ledc_update_duty(group, channel) != ESP_OK) {
log_e("ledc_update_duty failed");
return false;
}
ledc_set_duty(group, channel, duty);
ledc_update_duty(group, channel);
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);
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 0;
@ -403,8 +239,8 @@ uint32_t ledcReadFreq(uint8_t pin) {
if (!ledcRead(pin)) {
return 0;
}
uint8_t group = (bus->channel / SOC_LEDC_CHANNEL_NUM);
return ledc_get_freq(group, bus->timer_num);
uint8_t group = (bus->channel / 8), timer = ((bus->channel / 2) % 4);
return ledc_get_freq(group, timer);
}
return 0;
}
@ -418,15 +254,9 @@ uint32_t ledcWriteTone(uint8_t pin, uint32_t freq) {
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;
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;
ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = 10, .freq_hz = freq, .clk_cfg = clock_source};
if (ledc_timer_config(&ledc_timer) != ESP_OK) {
log_e("ledcWriteTone configuration failed!");
@ -434,7 +264,7 @@ uint32_t ledcWriteTone(uint8_t pin, uint32_t freq) {
}
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);
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);
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;
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;
ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = resolution, .freq_hz = freq, .clk_cfg = clock_source};
if (ledc_timer_config(&ledc_timer) != ESP_OK) {
log_e("ledcChangeFrequency failed!");
return 0;
}
bus->channel_resolution = resolution;
return ledc_get_freq(group, bus->timer_num);
return ledc_get_freq(group, timer);
}
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);
if (bus != NULL) {
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
esp_rom_gpio_connect_out_signal(
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
);
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);
#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 // ifdef CONFIG_IDF_TARGET_ESP32P4
return true;
}
return false;
@ -555,7 +372,7 @@ static bool ledcFadeConfig(uint8_t pin, uint32_t start_duty, uint32_t target_dut
}
#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.
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);
}
#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 int analog_frequency = 1000;
void analogWrite(uint8_t pin, int value) {

View file

@ -51,8 +51,6 @@ typedef struct {
uint8_t pin; // Pin assigned to channel
uint8_t channel; // Channel number
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;
void *arg;
#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);
//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
}
#endif

View file

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

View file

@ -32,10 +32,6 @@
#include "esp32c6/rom/gpio.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#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
#error Target CONFIG_IDF_TARGET is not supported
#endif

View file

@ -24,16 +24,14 @@
#ifdef CONFIG_APP_ROLLBACK_ENABLE
#include "esp_ota_ops.h"
#endif //CONFIG_APP_ROLLBACK_ENABLE
#include "esp_private/startup_internal.h"
#if (defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)) && SOC_BT_SUPPORTED && __has_include("esp_bt.h")
#ifdef CONFIG_BT_ENABLED
#include "esp_bt.h"
#endif
#endif //CONFIG_BT_ENABLED
#include <sys/time.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) \
&& !defined(CONFIG_IDF_TARGET_ESP32C5)
#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
#include "soc/rtc_cntl_reg.h"
#include "soc/syscon_reg.h"
#include "soc/apb_ctrl_reg.h"
#endif
#include "esp_task_wdt.h"
#include "esp32-hal.h"
@ -55,10 +53,6 @@
#include "esp32c6/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#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
#error Target CONFIG_IDF_TARGET is not supported
@ -153,36 +147,32 @@ void feedLoopWDT() {
#endif
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) {
log_e("Failed to add Core 0 IDLE task to WDT");
}
}
bool disableCore0WDT() {
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCore(0);
if (idle_0 == NULL || esp_task_wdt_status(idle_0) || esp_task_wdt_delete(idle_0) != ESP_OK) {
void disableCore0WDT() {
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
if (idle_0 == NULL || esp_task_wdt_delete(idle_0) != ESP_OK) {
log_e("Failed to remove Core 0 IDLE task from WDT");
return false;
}
return true;
}
#ifndef CONFIG_FREERTOS_UNICORE
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) {
log_e("Failed to add Core 1 IDLE task to WDT");
}
}
bool disableCore1WDT() {
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCore(1);
if (idle_1 == NULL || esp_task_wdt_status(idle_1) || esp_task_wdt_delete(idle_1) != ESP_OK) {
void disableCore1WDT() {
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
if (idle_1 == NULL || esp_task_wdt_delete(idle_1) != ESP_OK) {
log_e("Failed to remove Core 1 IDLE task from WDT");
return false;
}
return true;
}
#endif
@ -246,7 +236,7 @@ bool verifyRollbackLater() {
}
#endif
#if defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)
#ifdef CONFIG_BT_ENABLED
#if CONFIG_IDF_TARGET_ESP32
//overwritten in esp32-hal-bt.c
bool btInUse() __attribute__((weak));
@ -259,20 +249,11 @@ extern bool btInUse();
#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() {
//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;
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
#ifndef CONFIG_SPIRAM_BOOT_INIT
psramAddToHeap();
#endif
psramInit();
#endif
#ifdef CONFIG_APP_ROLLBACK_ENABLE
if (!verifyRollbackLater()) {
@ -308,7 +289,7 @@ void initArduino() {
if (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()) {
esp_bt_controller_mem_release(ESP_BT_MODE_BTDM);
}

View file

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

View file

@ -21,8 +21,7 @@ extern "C" {
#include "sdkconfig.h"
// Clear flags in Arduino IDE when PSRAM is disabled
#if defined(ESP32_ARDUINO_LIB_BUILDER) && !defined(BOARD_HAS_PSRAM)
#ifndef BOARD_HAS_PSRAM
#ifdef CONFIG_SPIRAM_SUPPORT
#undef CONFIG_SPIRAM_SUPPORT
#endif
@ -32,7 +31,6 @@ extern "C" {
#endif
bool psramInit();
bool psramAddToHeap();
bool psramFound();
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);
duty_percent = 0.5;
}
rmt_carrier_config_t carrier_cfg;
memset((void *)&carrier_cfg, 0, sizeof(rmt_carrier_config_t));
rmt_carrier_config_t carrier_cfg = {0};
carrier_cfg.duty_cycle = duty_percent; // duty cycle
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
@ -314,8 +313,7 @@ static bool _rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, bool bl
return false;
}
rmt_transmit_config_t transmit_cfg; // loop mode disabled
memset((void *)&transmit_cfg, 0, sizeof(rmt_transmit_config_t));
rmt_transmit_config_t transmit_cfg = {0}; // loop mode disabled
bool retCode = true;
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
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_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) {
// TX Channel
rmt_tx_channel_config_t tx_cfg;
memset((void *)&tx_cfg, 0, sizeof(rmt_tx_channel_config_t));
tx_cfg.gpio_num = pin;
// CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F80M for C6 -- CLK_XTAL for H2
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 {
// RX Channel
rmt_rx_channel_config_t rx_cfg;
memset((void *)&rx_cfg, 0, sizeof(rmt_rx_channel_config_t));
rx_cfg.gpio_num = pin;
// CLK_APB for ESP32|S2|S3|C3 -- CLK_PLL_F80M for C6 -- CLK_XTAL for H2
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
rmt_copy_encoder_config_t copy_encoder_config;
memset((void *)&copy_encoder_config, 0, sizeof(rmt_copy_encoder_config_t));
rmt_copy_encoder_config_t copy_encoder_config = {};
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);
goto Err;

View file

@ -22,15 +22,11 @@
#include "esp_attr.h"
#include "soc/spi_reg.h"
#include "soc/spi_struct.h"
#include "soc/periph_defs.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/rtc.h"
#ifndef CONFIG_IDF_TARGET_ESP32C5
#include "hal/clk_gate_ll.h"
#endif
#include "esp32-hal-periman.h"
#include "esp_private/periph_ctrl.h"
#include "esp_system.h"
#include "esp_intr_alloc.h"
@ -59,19 +55,12 @@
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/ets_sys.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
#error Target CONFIG_IDF_TARGET is not supported
#endif
struct spi_struct_t {
volatile spi_dev_t *dev;
spi_dev_t *dev;
#if !CONFIG_DISABLE_HAL_LOCKS
SemaphoreHandle_t lock;
#endif
@ -80,20 +69,20 @@ struct spi_struct_t {
int8_t miso;
int8_t mosi;
int8_t ss;
bool ss_invert;
};
#if CONFIG_IDF_TARGET_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_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_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) ? SPIQ_OUT_IDX : ((p == 1) ? FSPIQ_OUT_IDX : ((p == 2) ? SPI3_Q_OUT_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_FSPI_SS_IDX(n) ((n == 0) ? FSPICS0_OUT_IDX : ((n == 1) ? FSPICS1_OUT_IDX : ((n == 2) ? FSPICS2_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_SPI_SS_IDX(n) ((n == 0) ? SPICS0_OUT_IDX : ((n == 1) ? SPICS1_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_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
// 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_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_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 : 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))
#elif CONFIG_IDF_TARGET_ESP32P4
// 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
#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
// ESP32C3
#define SPI_COUNT (1)
@ -154,25 +125,27 @@ struct spi_struct_t {
#if CONFIG_DISABLE_HAL_LOCKS
#define SPI_MUTEX_LOCK()
#define SPI_MUTEX_UNLOCK()
// clang-format off
static spi_t _spi_bus_array[] = {
#if CONFIG_IDF_TARGET_ESP32S2 ||CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1, false},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 1, -1, -1, -1, -1, false}
#if CONFIG_IDF_TARGET_ESP32S2
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 0, -1, -1, -1, -1},
{(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
{(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
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1, false}
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5
{(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
{(spi_dev_t *)(DR_REG_SPI2_BASE), 0, -1, -1, -1, -1}
#else
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0, -1, -1, -1, -1, false},
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1, -1, -1, -1, -1, false},
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2, -1, -1, -1, -1, false},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3, -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},
{(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}
#endif
};
// clang-format on
#else
#define SPI_MUTEX_LOCK() \
do { \
@ -180,19 +153,23 @@ static spi_t _spi_bus_array[] = {
#define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock)
static spi_t _spi_bus_array[] = {
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4
{(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}
#if CONFIG_IDF_TARGET_ESP32S2
{(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
{(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
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1, false}
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5
{(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
{(spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0, -1, -1, -1, -1}
#else
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0, -1, -1, -1, -1, false},
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1, -1, -1, -1, -1, false},
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2, -1, -1, -1, -1, false},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3, -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},
{(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}
#endif
};
#endif
@ -363,7 +340,7 @@ bool spiAttachSS(spi_t *spi, uint8_t ss_num, int8_t ss) {
return false;
}
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));
spi->ss = ss;
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;
}
SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.val &= ~(ss_mask & SPI_SS_MASK_ALL);
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.val &= ~(ss_mask & SPI_SS_MASK_ALL);
#else
spi->dev->pin.val &= ~(ss_mask & SPI_SS_MASK_ALL);
#endif
SPI_MUTEX_UNLOCK();
}
@ -405,10 +383,11 @@ void spiDisableSSPins(spi_t *spi, uint8_t ss_mask) {
return;
}
SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.val |= (ss_mask & SPI_SS_MASK_ALL);
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.val |= (ss_mask & SPI_SS_MASK_ALL);
#else
spi->dev->pin.val |= (ss_mask & SPI_SS_MASK_ALL);
#endif
SPI_MUTEX_UNLOCK();
}
@ -433,21 +412,16 @@ void spiSSDisable(spi_t *spi) {
SPI_MUTEX_UNLOCK();
}
void spiSSInvert(spi_t *spi, bool invert) {
if (spi) {
spi->ss_invert = invert;
}
}
void spiSSSet(spi_t *spi) {
if (!spi) {
return;
}
SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.cs_keep_active = 1;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.cs_keep_active = 1;
#else
spi->dev->pin.cs_keep_active = 1;
#endif
SPI_MUTEX_UNLOCK();
}
@ -457,10 +431,11 @@ void spiSSClear(spi_t *spi) {
return;
}
SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.cs_keep_active = 0;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.cs_keep_active = 0;
#else
spi->dev->pin.cs_keep_active = 0;
#endif
SPI_MUTEX_UNLOCK();
}
@ -485,10 +460,11 @@ uint8_t spiGetDataMode(spi_t *spi) {
if (!spi) {
return 0;
}
#if CONFIG_IDF_TARGET_ESP32
bool idleEdge = spi->dev->pin.ck_idle_edge;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
bool idleEdge = spi->dev->misc.ck_idle_edge;
#else
bool idleEdge = spi->dev->pin.ck_idle_edge;
#endif
bool outEdge = spi->dev->user.ck_out_edge;
if (idleEdge) {
@ -510,35 +486,39 @@ void spiSetDataMode(spi_t *spi, uint8_t dataMode) {
SPI_MUTEX_LOCK();
switch (dataMode) {
case SPI_MODE1:
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.ck_idle_edge = 0;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
#endif
spi->dev->user.ck_out_edge = 1;
break;
case SPI_MODE2:
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.ck_idle_edge = 1;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
#endif
spi->dev->user.ck_out_edge = 1;
break;
case SPI_MODE3:
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.ck_idle_edge = 1;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
#endif
spi->dev->user.ck_out_edge = 0;
break;
case SPI_MODE0:
default:
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.ck_idle_edge = 0;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
#endif
spi->dev->user.ck_out_edge = 0;
break;
@ -584,10 +564,11 @@ static void spiInitBus(spi_t *spi) {
spi->dev->slave.trans_done = 0;
#endif
spi->dev->slave.val = 0;
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.val = 0;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.val = 0;
#else
spi->dev->pin.val = 0;
#endif
spi->dev->user.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) {
if (spi_num >= SPI_COUNT) {
log_e("SPI bus index %d is out of range", spi_num);
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) {
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);
} 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
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_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
}
#elif CONFIG_IDF_TARGET_ESP32P4
#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)
#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
periph_ll_reset(PERIPH_SPI2_MODULE);
periph_ll_enable_clk_clear_rst(PERIPH_SPI2_MODULE);
#endif
SPI_MUTEX_LOCK();
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.mst_clk_sel = 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.rx_seg_trans_clr_en = 1;
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;
int 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;
#else
spi->dev->data_buf[i] = 0x00000000;
@ -739,7 +697,7 @@ void spiWaitReady(spi_t *spi) {
#if CONFIG_IDF_TARGET_ESP32S2
#define usr_mosi_dbitlen usr_mosi_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_miso_dbitlen ms_data_bitlen
#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;
#endif
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];
#else
spi->dev->data_buf[i] = data[i];
#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;
while (spi->dev->cmd.update);
#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->miso_dlen.usr_miso_dbitlen = (len * 32) - 1;
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];
#else
spi->dev->data_buf[i] = data[i];
#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;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while (spi->dev->cmd.usr);
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;
#else
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
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
@ -840,18 +798,18 @@ uint8_t spiTransferByte(spi_t *spi, uint8_t data) {
SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
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;
#else
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
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
@ -905,18 +863,18 @@ uint16_t spiTransferWord(spi_t *spi, uint16_t data) {
SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
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;
#else
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
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
@ -964,18 +922,18 @@ uint32_t spiTransferLong(spi_t *spi, uint32_t data) {
SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
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;
#else
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);
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
#else
spi->dev->data_buf[i] = wordsBuf[i]; //copy buffer to spi fifo
#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;
while (spi->dev->cmd.update);
#endif
@ -1031,7 +989,7 @@ static void __spiTransferBytes(spi_t *spi, const uint8_t *data, uint8_t *out, ui
if (out) {
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
#else
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;
switch (dataMode) {
case SPI_MODE1:
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.ck_idle_edge = 0;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
#endif
spi->dev->user.ck_out_edge = 1;
break;
case SPI_MODE2:
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.ck_idle_edge = 1;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
#endif
spi->dev->user.ck_out_edge = 1;
break;
case SPI_MODE3:
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.ck_idle_edge = 1;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
#endif
spi->dev->user.ck_out_edge = 0;
break;
case SPI_MODE0:
default:
#if CONFIG_IDF_TARGET_ESP32
spi->dev->pin.ck_idle_edge = 0;
#else
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 \
|| CONFIG_IDF_TARGET_ESP32H2
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
#endif
spi->dev->user.ck_out_edge = 0;
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.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
spi->dev->cmd.update = 1;
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
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
@ -1191,18 +1153,18 @@ uint8_t spiTransferByteNL(spi_t *spi, uint8_t data) {
}
spi->dev->mosi_dlen.usr_mosi_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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
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;
#else
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
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
@ -1243,18 +1205,18 @@ uint16_t spiTransferShortNL(spi_t *spi, uint16_t data) {
}
spi->dev->mosi_dlen.usr_mosi_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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
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;
#else
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
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
@ -1298,18 +1260,18 @@ uint32_t spiTransferLongNL(spi_t *spi, uint32_t data) {
}
spi->dev->mosi_dlen.usr_mosi_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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
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;
#else
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;
#endif
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];
#else
spi->dev->data_buf[i] = data[i];
#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;
while (spi->dev->cmd.update);
#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;
if (data) {
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];
#else
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 {
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;
#else
spi->dev->data_buf[i] = 0xFFFFFFFF;
#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;
while (spi->dev->cmd.update);
#endif
@ -1403,13 +1365,13 @@ void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint
if (result) {
if (c_len & 3) {
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;
#else
result[i] = spi->dev->data_buf[i];
#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;
#else
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 {
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;
#else
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->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;
#else
spi->dev->data_buf[0] = data;
#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;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
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;
#else
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 (l_bytes && i == (c_longs - 1)) {
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]);
#else
MSB_16_SET(spi->dev->data_buf[i], data[i]);
#endif
} 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;
#else
spi->dev->data_buf[i] = data[i] & 0xFF;
#endif
}
} 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]);
#else
MSB_PIX_SET(spi->dev->data_buf[i], data[i]);
#endif
}
} 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];
#else
spi->dev->data_buf[i] = data[i];
#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;
while (spi->dev->cmd.update);
#endif
@ -1566,7 +1528,7 @@ typedef union {
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_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 reserved : 9; /*reserved*/
#else
@ -1611,7 +1573,7 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq) {
while (calPreVari++ <= 1) {
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) {
reg.clkdiv_pre = 0xF;
#else

View file

@ -27,13 +27,19 @@ extern "C" {
#include <stdbool.h>
#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 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
#else
#define FSPI 0 // ESP32C2, C3, C6, H2, S2, S3, P4 - SPI 2 bus
#define HSPI 1 // ESP32S2, S3, P4 - SPI 3 bus
#endif
// 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 spiWaitReady(spi_t *spi);
//invert hardware SS
void spiSSInvert(spi_t *spi, bool invert);
uint32_t spiGetClockDiv(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