diff --git a/tools/ci/check-cmakelists.sh b/.github/scripts/check-cmakelists.sh similarity index 95% rename from tools/ci/check-cmakelists.sh rename to .github/scripts/check-cmakelists.sh index 4d11359cf80..88eb3dfbc4b 100755 --- a/tools/ci/check-cmakelists.sh +++ b/.github/scripts/check-cmakelists.sh @@ -8,8 +8,6 @@ set -e -cd "`dirname $0`/.." # cd to arduino-esp32 root - # pull all submodules git submodule update --init --recursive diff --git a/.github/scripts/install-arduino-core-esp32.sh b/.github/scripts/install-arduino-core-esp32.sh new file mode 100755 index 00000000000..cf1026d6a71 --- /dev/null +++ b/.github/scripts/install-arduino-core-esp32.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +export ARDUINO_ESP32_PATH="$ARDUINO_USR_PATH/hardware/espressif/esp32" +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" + + echo "Installing Python Serial ..." + pip install pyserial > /dev/null + + if [ "$OS_IS_WINDOWS" == "1" ]; then + echo "Installing Python Requests ..." + pip install requests > /dev/null + fi + + if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then + echo "Linking Core..." + 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 + git submodule update --init --recursive > /dev/null 2>&1 + + echo "Installing Platform Tools ..." + cd tools && python get.py + cd $script_init_path + + echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'" + echo "" +fi diff --git a/.github/scripts/install-arduino-ide.sh b/.github/scripts/install-arduino-ide.sh new file mode 100755 index 00000000000..7e268b1ff7e --- /dev/null +++ b/.github/scripts/install-arduino-ide.sh @@ -0,0 +1,220 @@ +#!/bin/bash + +#OSTYPE: 'linux-gnu', ARCH: 'x86_64' => linux64 +#OSTYPE: 'msys', ARCH: 'x86_64' => win32 +#OSTYPE: 'darwin18', ARCH: 'i386' => macos + +OSBITS=`arch` +if [[ "$OSTYPE" == "linux"* ]]; then + export OS_IS_LINUX="1" + ARCHIVE_FORMAT="tar.xz" + if [[ "$OSBITS" == "i686" ]]; then + OS_NAME="linux32" + elif [[ "$OSBITS" == "x86_64" ]]; then + OS_NAME="linux64" + elif [[ "$OSBITS" == "armv7l" || "$OSBITS" == "aarch64" ]]; then + OS_NAME="linuxarm" + else + OS_NAME="$OSTYPE-$OSBITS" + echo "Unknown OS '$OS_NAME'" + exit 1 + fi +elif [[ "$OSTYPE" == "darwin"* ]]; then + export OS_IS_MACOS="1" + ARCHIVE_FORMAT="zip" + OS_NAME="macosx" +elif [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then + export OS_IS_WINDOWS="1" + ARCHIVE_FORMAT="zip" + OS_NAME="windows" +else + OS_NAME="$OSTYPE-$OSBITS" + echo "Unknown OS '$OS_NAME'" + exit 1 +fi +export OS_NAME + +ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp" +ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp" + +if [ "$OS_IS_MACOS" == "1" ]; then + export ARDUINO_IDE_PATH="/Applications/Arduino.app/Contents/Java" + export ARDUINO_USR_PATH="$HOME/Documents/Arduino" +elif [ "$OS_IS_WINDOWS" == "1" ]; then + export ARDUINO_IDE_PATH="$HOME/arduino_ide" + export ARDUINO_USR_PATH="$HOME/Documents/Arduino" +else + export ARDUINO_IDE_PATH="$HOME/arduino_ide" + export ARDUINO_USR_PATH="$HOME/Arduino" +fi + +if [ ! -d "$ARDUINO_IDE_PATH" ]; then + echo "Installing Arduino IDE on $OS_NAME ..." + echo "Downloading 'arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT' to 'arduino.$ARCHIVE_FORMAT' ..." + if [ "$OS_IS_LINUX" == "1" ]; then + wget -O "arduino.$ARCHIVE_FORMAT" "https://www.arduino.cc/download.php?f=/arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1 + echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..." + tar xf "arduino.$ARCHIVE_FORMAT" > /dev/null + mv arduino-nightly "$ARDUINO_IDE_PATH" + else + curl -o "arduino.$ARCHIVE_FORMAT" -L "https://www.arduino.cc/download.php?f=/arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1 + echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..." + unzip "arduino.$ARCHIVE_FORMAT" > /dev/null + if [ "$OS_IS_MACOS" == "1" ]; then + mv "Arduino.app" "/Applications/Arduino.app" + else + mv arduino-nightly "$ARDUINO_IDE_PATH" + fi + fi + rm -rf "arduino.$ARCHIVE_FORMAT" + + mkdir -p "$ARDUINO_USR_PATH/libraries" + mkdir -p "$ARDUINO_USR_PATH/hardware" + + echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'" + echo "" +fi + +function build_sketch(){ # build_sketch [extra-options] + if [ "$#" -lt 2 ]; then + echo "ERROR: Illegal number of parameters" + echo "USAGE: build_sketch [extra-options]" + return 1 + fi + + local fqbn="$1" + local sketch="$2" + local xtra_opts="$3" + local win_opts="" + if [ "$OS_IS_WINDOWS" == "1" ]; then + 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" + fi + + echo "" + echo "Compiling '"$(basename "$sketch")"' ..." + mkdir -p "$ARDUINO_BUILD_DIR" + mkdir -p "$ARDUINO_CACHE_DIR" + $ARDUINO_IDE_PATH/arduino-builder -compile -logger=human -core-api-version=10810 \ + -fqbn=$fqbn \ + -warnings="all" \ + -tools "$ARDUINO_IDE_PATH/tools-builder" \ + -tools "$ARDUINO_IDE_PATH/tools" \ + -built-in-libraries "$ARDUINO_IDE_PATH/libraries" \ + -hardware "$ARDUINO_IDE_PATH/hardware" \ + -hardware "$ARDUINO_USR_PATH/hardware" \ + -libraries "$ARDUINO_USR_PATH/libraries" \ + -build-cache "$ARDUINO_CACHE_DIR" \ + -build-path "$ARDUINO_BUILD_DIR" \ + $win_opts $xtra_opts "$sketch" +} + +function count_sketches() # count_sketches +{ + 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; + if [[ -f "$sketchdir/.test.skip" ]]; then + continue + fi + echo $sketch >> sketches.txt + sketchnum=$(($sketchnum + 1)) + done + return $sketchnum +} + +function build_sketches() # build_sketches [extra-options] +{ + local fqbn=$1 + local examples=$2 + local chunk_idex=$3 + local chunks_num=$4 + local xtra_opts=$5 + + if [ "$#" -lt 2 ]; then + echo "ERROR: Illegal number of parameters" + echo "USAGE: build_sketches [ ] [extra-options]" + return 1 + fi + + if [ "$#" -lt 4 ]; then + chunk_idex="0" + chunks_num="1" + xtra_opts=$3 + 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) + if [ "${sketchdirname}.ino" != "$sketchname" ] \ + || [ -f "$sketchdir/.test.skip" ]; then + continue + fi + sketchnum=$(($sketchnum + 1)) + if [ "$sketchnum" -le "$start_index" ] \ + || [ "$sketchnum" -gt "$end_index" ]; then + continue + fi + build_sketch "$fqbn" "$sketch" "$xtra_opts" + local result=$? + if [ $result -ne 0 ]; then + return $result + fi + done + return 0 +} diff --git a/.github/scripts/install-platformio-esp32.sh b/.github/scripts/install-platformio-esp32.sh new file mode 100755 index 00000000000..ce6de4a2ef4 --- /dev/null +++ b/.github/scripts/install-platformio-esp32.sh @@ -0,0 +1,153 @@ +#!/bin/bash + +export PLATFORMIO_ESP32_PATH="$HOME/.platformio/packages/framework-arduinoespressif32" + +echo "Installing Python Wheel ..." +pip install wheel > /dev/null 2>&1 + +echo "Installing PlatformIO ..." +pip install -U https://github.com/platformio/platformio/archive/develop.zip > /dev/null 2>&1 + +echo "Installing Platform ESP32 ..." +python -m platformio platform install https://github.com/platformio/platform-espressif32.git#feature/stage > /dev/null 2>&1 + +echo "Replacing the framework version ..." +if [[ "$OSTYPE" == "darwin"* ]]; then + sed 's/https:\/\/github\.com\/espressif\/arduino-esp32\.git/*/' "$HOME/.platformio/platforms/espressif32/platform.json" > "platform.json" + mv -f "platform.json" "$HOME/.platformio/platforms/espressif32/platform.json" +else + sed -i 's/https:\/\/github\.com\/espressif\/arduino-esp32\.git/*/' "$HOME/.platformio/platforms/espressif32/platform.json" +fi + +if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then + echo "Linking Core..." + ln -s $GITHUB_WORKSPACE "$PLATFORMIO_ESP32_PATH" +else + echo "Cloning Core Repository ..." + git clone 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 + if [ "$#" -lt 2 ]; then + echo "ERROR: Illegal number of parameters" + echo "USAGE: build_pio_sketch " + return 1 + fi + + local board="$1" + local sketch="$2" + local sketch_dir=$(dirname "$sketch") + echo "" + echo "Compiling '"$(basename "$sketch")"' ..." + python -m platformio ci --board "$board" "$sketch_dir" --project-option="board_build.partitions = huge_app.csv" +} + +function count_sketches() # count_sketches +{ + 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; + if [[ -f "$sketchdir/.test.skip" ]]; then + continue + fi + echo $sketch >> sketches.txt + sketchnum=$(($sketchnum + 1)) + done + return $sketchnum +} + +function build_pio_sketches() # build_pio_sketches +{ + if [ "$#" -lt 2 ]; then + echo "ERROR: Illegal number of parameters" + echo "USAGE: build_pio_sketches [ ]" + return 1 + fi + + local board=$1 + local examples=$2 + local chunk_idex=$3 + local chunks_num=$4 + + if [ "$#" -lt 4 ]; 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) + if [ "${sketchdirname}.ino" != "$sketchname" ] \ + || [ -f "$sketchdir/.test.skip" ]; then + continue + fi + sketchnum=$(($sketchnum + 1)) + if [ "$sketchnum" -le "$start_index" ] \ + || [ "$sketchnum" -gt "$end_index" ]; then + continue + fi + build_pio_sketch "$board" "$sketch" + local result=$? + if [ $result -ne 0 ]; then + return $result + fi + done + return 0 +} diff --git a/package/merge_packages.py b/.github/scripts/merge_packages.py similarity index 100% rename from package/merge_packages.py rename to .github/scripts/merge_packages.py diff --git a/.github/scripts/on-pages.sh b/.github/scripts/on-pages.sh new file mode 100644 index 00000000000..1b265f91adb --- /dev/null +++ b/.github/scripts/on-pages.sh @@ -0,0 +1,131 @@ +#/bin/bash +set -e + +function get_file_size(){ + local file="$1" + if [[ "$OSTYPE" == "darwin"* ]]; then + eval `stat -s "$file"` + local res="$?" + echo "$st_size" + return $res + else + stat --printf="%s" "$file" + return $? + fi +} + +#git_remove_from_pages +function git_remove_from_pages(){ + local path=$1 + 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 + 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(){ + local path=$1 + local src=$2 + + if [ ! -f "$src" ]; then + >&2 echo "Input is not a file! Aborting..." + return 1 + fi + + 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="" + + if [ $type == "file" ]; then + sha=`echo "$info" | jq -r '.sha'` + sha=",\"sha\":\"$sha\"" + message="Updating $message" + elif [ ! $type == "null" ]; then + >&2 echo "Wrong type '$type'" + return 1 + else + message="Creating $message" + fi + + 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(){ + local path=$1 + local file="$2" + 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 + >&2 echo "ERROR: Uploaded size does not match! $up_size != $size" + #git_delete_asset + return 1 + fi + echo "$upload_res" | jq -r '.content.download_url' + return $? +} + +EVENT_JSON=`cat $GITHUB_EVENT_PATH` + +pages_added=`echo "$EVENT_JSON" | jq -r '.commits[].added[]'` +pages_modified=`echo "$EVENT_JSON" | jq -r '.commits[].modified[]'` +pages_removed=`echo "$EVENT_JSON" | jq -r '.commits[].removed[]'` + +for page in $pages_added; do + if [[ $page != "README.md" && $page != "docs/"* ]]; then + continue + fi + echo "Adding '$page' to pages ..." + if [[ $page == "README.md" ]]; then + git_safe_upload_to_pages "index.md" "README.md" + else + git_safe_upload_to_pages "$page" "$page" + fi +done + +for page in $pages_modified; do + if [[ $page != "README.md" && $page != "docs/"* ]]; then + continue + fi + echo "Modifying '$page' ..." + if [[ $page == "README.md" ]]; then + git_safe_upload_to_pages "index.md" "README.md" + else + git_safe_upload_to_pages "$page" "$page" + fi +done + +for page in $pages_removed; do + if [[ $page != "README.md" && $page != "docs/"* ]]; then + continue + fi + echo "Removing '$page' from pages ..." + if [[ $page == "README.md" ]]; then + git_remove_from_pages "README.md" > /dev/null + else + git_remove_from_pages "$page" > /dev/null + fi +done + +echo +echo "DONE!" diff --git a/.github/scripts/on-push.sh b/.github/scripts/on-push.sh new file mode 100755 index 00000000000..e0e14ec2b26 --- /dev/null +++ b/.github/scripts/on-push.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +set -e + +if [ ! -z "$TRAVIS_TAG" ]; then + echo "Skipping Test: Tagged build" + exit 0 +fi + +if [ ! -z "$GITHUB_WORKSPACE" ]; then + export TRAVIS_BUILD_DIR="$GITHUB_WORKSPACE" + export TRAVIS_REPO_SLUG="$GITHUB_REPOSITORY" +elif [ ! -z "$TRAVIS_BUILD_DIR" ]; then + export GITHUB_WORKSPACE="$TRAVIS_BUILD_DIR" + export GITHUB_REPOSITORY="$TRAVIS_REPO_SLUG" +else + export GITHUB_WORKSPACE="$PWD" + export GITHUB_REPOSITORY="espressif/arduino-esp32" +fi + +CHUNK_INDEX=$1 +CHUNKS_CNT=$2 +BUILD_PIO=0 +if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then + CHUNK_INDEX=0 + CHUNKS_CNT=1 +elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ]; then + CHUNK_INDEX=$CHUNKS_CNT +elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then + BUILD_PIO=1 +fi + +echo "Updating submodules ..." +git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1 + +if [ "$BUILD_PIO" -eq 0 ]; then + # ArduinoIDE Test + FQBN="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app" + source ./.github/scripts/install-arduino-ide.sh + source ./.github/scripts/install-arduino-core-esp32.sh + if [ "$OS_IS_WINDOWS" == "1" ]; then + build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \ + build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \ + build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/AzureIoT/examples/GetStarted/GetStarted.ino" && \ + build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino" + elif [ "$OS_IS_MACOS" == "1" ]; then + build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \ + build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \ + build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \ + build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \ + build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/AzureIoT/examples/GetStarted/GetStarted.ino" && \ + build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino" + else + # CMake Test + if [ "$CHUNK_INDEX" -eq 0 ]; then + bash "$ARDUINO_ESP32_PATH/.github/scripts/check-cmakelists.sh" + fi + build_sketches "$FQBN" "$ARDUINO_ESP32_PATH/libraries" "$CHUNK_INDEX" "$CHUNKS_CNT" + fi +else + # PlatformIO Test + source ./.github/scripts/install-platformio-esp32.sh + BOARD="esp32dev" + build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \ + build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \ + build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \ + build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \ + build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/AzureIoT/examples/GetStarted/GetStarted.ino" && \ + build_pio_sketch "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino" + #build_pio_sketches esp32dev "$PLATFORMIO_ESP32_PATH/libraries" +fi diff --git a/.github/scripts/on-release.sh b/.github/scripts/on-release.sh new file mode 100755 index 00000000000..e5e320099dd --- /dev/null +++ b/.github/scripts/on-release.sh @@ -0,0 +1,380 @@ +#!/bin/bash + +if [ ! $GITHUB_EVENT_NAME == "release" ]; then + echo "Wrong event '$GITHUB_EVENT_NAME'!" + exit 1 +fi + +EVENT_JSON=`cat $GITHUB_EVENT_PATH` + +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 + 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_BODY=`echo $EVENT_JSON | jq -r '.release.body'` + +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" + +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" + +function get_file_size(){ + local file="$1" + if [[ "$OSTYPE" == "darwin"* ]]; then + eval `stat -s "$file"` + local res="$?" + echo "$st_size" + return $res + else + stat --printf="%s" "$file" + return $? + fi +} + +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(){ + local file="$1" + 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 + >&2 echo "ERROR: Uploaded size does not match! $up_size != $size" + #git_delete_asset + return 1 + fi + echo "$upload_res" | jq -r '.browser_download_url' + return $? +} + +function git_upload_to_pages(){ + local path=$1 + local src=$2 + + if [ ! -f "$src" ]; then + >&2 echo "Input is not a file! Aborting..." + return 1 + fi + + 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="" + + if [ $type == "file" ]; then + sha=`echo "$info" | jq -r '.sha'` + sha=",\"sha\":\"$sha\"" + message="Updating $message" + elif [ ! $type == "null" ]; then + >&2 echo "Wrong type '$type'" + return 1 + else + message="Creating $message" + fi + + 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(){ + local path=$1 + local file="$2" + 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 + >&2 echo "ERROR: Uploaded size does not match! $up_size != $size" + #git_delete_asset + return 1 + fi + echo "$upload_res" | jq -r '.content.download_url' + return $? +} + +function merge_package_json(){ + local jsonLink=$1 + local jsonOut=$2 + local old_json=$OUTPUT_DIR/oldJson.json + local merged_json=$OUTPUT_DIR/mergedJson.json + + 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 + if [ $? -ne 0 ]; then echo "ERROR: Download Failed! $?"; exit 1; fi + + echo "Creating new JSON ..." + set +e + stdbuf -oL python "$PACKAGE_JSON_MERGE" "$jsonOut" "$old_json" > "$merged_json" + set -e + + set -v + if [ ! -s $merged_json ]; then + rm -f "$merged_json" + echo "Nothing to merge" + else + rm -f "$jsonOut" + mv "$merged_json" "$jsonOut" + echo "JSON data successfully merged" + fi + rm -f "$old_json" + set +v +} + +set -e + +## +## PACKAGE ZIP +## + +mkdir -p "$OUTPUT_DIR" +PKG_DIR="$OUTPUT_DIR/$PACKAGE_NAME" +PACKAGE_ZIP="$PACKAGE_NAME.zip" + +echo "Updating submodules ..." +git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1 + +mkdir -p "$PKG_DIR/tools" + +# Copy all core files to the package folder +echo "Copying files for packaging ..." +cp -f "$GITHUB_WORKSPACE/boards.txt" "$PKG_DIR/" +cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/" +cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/" +cp -Rf "$GITHUB_WORKSPACE/libraries" "$PKG_DIR/" +cp -Rf "$GITHUB_WORKSPACE/variants" "$PKG_DIR/" +cp -f "$GITHUB_WORKSPACE/tools/espota.exe" "$PKG_DIR/tools/" +cp -f "$GITHUB_WORKSPACE/tools/espota.py" "$PKG_DIR/tools/" +cp -f "$GITHUB_WORKSPACE/tools/esptool.py" "$PKG_DIR/tools/" +cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.py" "$PKG_DIR/tools/" +cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.exe" "$PKG_DIR/tools/" +cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/" +cp -Rf "$GITHUB_WORKSPACE/tools/sdk" "$PKG_DIR/tools/" + +# Remove unnecessary files in the package folder +echo "Cleaning up folders ..." +find "$PKG_DIR" -name '*.DS_Store' -exec rm -f {} \; +find "$PKG_DIR" -name '*.git*' -type f -delete + +# Replace tools locations in platform.txt +echo "Generating platform.txt..." +cat "$GITHUB_WORKSPACE/platform.txt" | \ +sed "s/version=.*/version=$ver$extent/g" | \ +sed 's/runtime.tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}\/tools\/xtensa-esp32-elf//g' | \ +sed 's/tools.esptool_py.path={runtime.platform.path}\/tools\/esptool/tools.esptool_py.path=\{runtime.tools.esptool_py.path\}/g' \ + > "$PKG_DIR/platform.txt" + +# 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" + +# 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 + +# 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"` +popd >/dev/null +rm -rf "$PKG_DIR" +echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA" +echo + +# Upload package to release page +echo "Uploading package to release page ..." +PACKAGE_URL=`git_safe_upload_asset "$PACKAGE_PATH"` +echo "Package Uploaded" +echo "Download URL: $PACKAGE_URL" +echo + +## +## PACKAGE JSON +## + +# Construct JQ argument with package data +jq_arg=".packages[0].platforms[0].version = \"$RELEASE_TAG\" | \ + .packages[0].platforms[0].url = \"$PACKAGE_URL\" |\ + .packages[0].platforms[0].archiveFileName = \"$PACKAGE_ZIP\" |\ + .packages[0].platforms[0].size = \"$PACKAGE_SIZE\" |\ + .packages[0].platforms[0].checksum = \"SHA-256:$PACKAGE_SHA\"" + +# Generate package JSONs +echo "Genarating $PACKAGE_JSON_DEV ..." +cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV" +if [ "$RELEASE_PRE" == "false" ]; then + echo "Genarating $PACKAGE_JSON_REL ..." + cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_REL" +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 + +set +e +prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name') +prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name') +shopt -s nocasematch +if [ "$prev_any_release" == "$RELEASE_TAG" ]; then + prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name') + prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name') +fi +COMMITS_SINCE_RELEASE="$prev_any_release" +shopt -u nocasematch +set -e + +# Merge package JSONs with previous releases +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" +fi + +if [ "$RELEASE_PRE" == "false" ]; then + COMMITS_SINCE_RELEASE="$prev_release" + 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" + fi +fi + +echo "Previous Release: $prev_release" +echo "Previous (any)release: $prev_any_release" +echo + +# 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 +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 +fi + +## +## RELEASE NOTES +## + +# Create release notes +echo "Preparing release notes ..." +releaseNotes="" + +# Process annotated tags +relNotesRaw=`git -C "$GITHUB_WORKSPACE" show -s --format=%b $RELEASE_TAG` +readarray -t msgArray <<<"$relNotesRaw" +arrLen=${#msgArray[@]} +if [ $arrLen > 3 ] && [ "${msgArray[0]:0:3}" == "tag" ]; then + ind=3 + while [ $ind -lt $arrLen ]; do + if [ $ind -eq 3 ]; then + releaseNotes="#### ${msgArray[ind]}" + releaseNotes+=$'\r\n' + else + oneLine="$(echo -e "${msgArray[ind]}" | sed -e 's/^[[:space:]]*//')" + if [ ${#oneLine} -gt 0 ]; then + if [ "${oneLine:0:2}" == "* " ]; then oneLine=$(echo ${oneLine/\*/-}); fi + if [ "${oneLine:0:2}" != "- " ]; then releaseNotes+="- "; fi + releaseNotes+="$oneLine" + releaseNotes+=$'\r\n' + fi + fi + let ind=$ind+1 + done +fi + +# Append Commit Messages +if [ ! -z "$COMMITS_SINCE_RELEASE" ] && [ "$COMMITS_SINCE_RELEASE" != "null" ]; then + echo "Getting commits since $COMMITS_SINCE_RELEASE ..." + commitFile=$OUTPUT_DIR/commits.txt + git -C "$GITHUB_WORKSPACE" log --oneline $COMMITS_SINCE_RELEASE.. > "$OUTPUT_DIR/commits.txt" + releaseNotes+=$'\r\n##### Commits\r\n' + IFS=$'\n' + for next in `cat $commitFile` + do + IFS=' ' read -r commitId commitMsg <<< "$next" + commitLine="- [$commitId](https://github.com/$GITHUB_REPOSITORY/commit/$commitId) $commitMsg" + releaseNotes+="$commitLine" + releaseNotes+=$'\r\n' + done + rm -f $commitFile +fi + +# Prepend the original release body +if [ "${RELEASE_BODY: -1}" == $'\r' ]; then + RELEASE_BODY="${RELEASE_BODY:0:-1}" +else + RELEASE_BODY="$RELEASE_BODY" +fi +RELEASE_BODY+=$'\r\n' +releaseNotes="$RELEASE_BODY$releaseNotes" + +# Update release page +echo "Updating release notes ..." +releaseNotes=$(printf '%s' "$releaseNotes" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))') +releaseNotes=${releaseNotes:1:-1} +curlData="{\"body\": \"$releaseNotes\"}" +releaseData=`curl --data "$curlData" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID?access_token=$GITHUB_TOKEN" 2>/dev/null` +if [ $? -ne 0 ]; then echo "ERROR: Updating Release Failed: $?"; exit 1; fi +echo "Release notes successfully updated" +echo + +## +## SUBMODULE VERSIONS +## + +# Upload submodules versions +echo "Generating submodules.txt ..." +git -C "$GITHUB_WORKSPACE" submodule status > "$OUTPUT_DIR/submodules.txt" +echo "Uploading submodules.txt ..." +echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/submodules.txt"` +echo "" +set +e + +## +## DONE +## +echo "DONE!" diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml new file mode 100644 index 00000000000..f111f3aa254 --- /dev/null +++ b/.github/workflows/gh-pages.yml @@ -0,0 +1,21 @@ +name: GitHub Pages CI + +on: + push: + branches: + - master + paths: + - 'README.md' + - 'docs/**' + +jobs: + + build-pages: + name: Build GitHub Pages + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Copy Files + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash ./.github/scripts/on-pages.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index baa6a22041c..00000000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,376 +0,0 @@ -name: ESP32 Arduino CI - -on: - push: - branches: - - master - - release/* - pull_request: - -jobs: - - build-arduino-0: - name: Build Arduino IDE Tests 0 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Run CMake Check - run: ./tools/ci/check-cmakelists.sh - - - name: Install Arduino IDE - env: - #ESP32_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 0 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-1: - name: Build Arduino IDE Tests 1 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 1 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-2: - name: Build Arduino IDE Tests 2 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 2 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-3: - name: Build Arduino IDE Tests 3 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 3 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-4: - name: Build Arduino IDE Tests 4 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 4 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-5: - name: Build Arduino IDE Tests 5 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 5 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-6: - name: Build Arduino IDE Tests 6 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 6 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-7: - name: Build Arduino IDE Tests 7 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 7 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-8: - name: Build Arduino IDE Tests 8 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 8 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-9: - name: Build Arduino IDE Tests 9 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 9 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-10: - name: Build Arduino IDE Tests 10 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 10 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-11: - name: Build Arduino IDE Tests 11 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 11 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-12: - name: Build Arduino IDE Tests 12 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 12 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-13: - name: Build Arduino IDE Tests 13 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 13 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-14: - name: Build Arduino IDE Tests 14 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 14 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-15: - name: Build Arduino IDE Tests 15 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 15 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-16: - name: Build Arduino IDE Tests 16 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 16 18 - - name: Sketch Sizes - run: cat size.log - - build-arduino-17: - name: Build Arduino IDE Tests 17 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-arduino-ide.sh - - name: Test Arduino IDE - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/test-arduino-ide.sh 17 18 - - name: Sketch Sizes - run: cat size.log - - - build-platformio: - name: Build PlatformIO Tests - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Pull submodules - run: git submodule update --init --recursive - - name: Install Python Wheel - run: pip install wheel - - name: Install GCC Toolchain - run: cd tools && python get.py - - name: Install PlatformIO - env: - TRAVIS_BUILD_DIR: ${{ github.workspace }} - run: ./tools/ci/prep-platformio.sh - - name: Test PlatformIO - run: ./tools/ci/test-platformio.sh diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml new file mode 100644 index 00000000000..42d4735f106 --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,49 @@ +name: ESP32 Arduino CI + +on: + push: + branches: + - master + - release/* + pull_request: + +jobs: + + # Ubuntu + build-arduino-linux: + name: Arduino ${{ matrix.chunk }} on ubuntu-latest + runs-on: ubuntu-latest + strategy: + matrix: + chunk: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] + + steps: + - uses: actions/checkout@v1 + - name: Build Sketches + run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} 15 + + # Windows and MacOS + build-arduino-win-mac: + name: Arduino on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [windows-latest, macOS-latest] + + steps: + - uses: actions/checkout@v1 + - name: Build Sketches + run: bash ./.github/scripts/on-push.sh + + # PlatformIO on Windows, Ubuntu and Mac + build-platformio: + name: PlatformIO on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + + steps: + - uses: actions/checkout@v1 + - name: Build Sketches + run: bash ./.github/scripts/on-push.sh 1 1 #equal and non-zero to trigger PIO diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000000..83b625164f7 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,17 @@ +name: ESP32 Arduino Release + +on: + release: + types: published + +jobs: + build: + name: Publish Release + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@master + - name: Build Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash ./.github/scripts/on-release.sh diff --git a/.travis.yml b/.travis.yml index 906beec981d..2fb1dc44dc9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,42 +21,27 @@ jobs: - name: "Build Arduino 0" if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) stage: build - script: $TRAVIS_BUILD_DIR/tools/ci/build-tests.sh 0 4 + script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 0 10 - name: "Build Arduino 1" if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) stage: build - script: $TRAVIS_BUILD_DIR/tools/ci/build-tests.sh 1 4 + script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 10 - name: "Build Arduino 2" if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) stage: build - script: $TRAVIS_BUILD_DIR/tools/ci/build-tests.sh 2 4 + script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 2 10 - name: "Build Arduino 3" if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) stage: build - script: $TRAVIS_BUILD_DIR/tools/ci/build-tests.sh 3 4 + script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 3 10 - name: "Build PlatformIO" if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) stage: build - script: $TRAVIS_BUILD_DIR/tools/ci/build-tests.sh 4 4 - - - name: "Package & Deploy" - if: tag IS present - stage: deploy - env: - - secure: "l/4Dt+KQ/mACtGAHDUsPr66fUte840PZoQ4xpPikqWZI0uARu4l+Ym7+sHinnT6fBqrj8AJeBYGz4nFa8NK4LutZn9mSD40w+sxl0wSV4oHV8rzKe3Cd8+sMG3+o33yWoikMNjSvqa73Q0rm+SgrlInNdZbuAyixL+a2alaWSnGPm4F2xwUGj+S33TOy5P/Xp77CYtCV5S8vzyk/eEdNhoF0GYePJVdfuzCOUjXMyT5OWxORkzzQ7Hnn/Ka/RDfV8Si4HgujLQBrK5q6iPnNBFqBSqilYBepSMn4opnOBpIm0SCgePz7XQEFC83buA7GUcnCnfg38bf+dCwHaODf1d1PmqVRYt2QmfinexXtM4afAtL0iBUDtvrfnXHzwW9w82VeZhpbJSVh9DUQvB0IlsZeCz9J9PUBAi3N+SMX+9l+BomYwRUlPuKY+Ef2JKk9q6mxtUkky5R0daAlVxEhpVdQks1rT+T+NMoDMemxQ3SKEiqAHh6EgHecruszffmZ71uLX9MpERpew0qN+UFiafws+jkTjx+3yF9yut0Hf9sMbeAYzzkGzRqJTUEBJ6B29Cql8M0yRXCNN/8wuuTHhG8esstozga4ZQoIVrq7mEAgup376PTcNfr1+imbbWVQ7lJdYIuDe6OS5V3OX6np11vgK/DbhfyzvQv9Z1zAGnM=" - - REMOTE_URL=https://github.com/$TRAVIS_REPO_SLUG/releases/download/$TRAVIS_TAG - script: bash $TRAVIS_BUILD_DIR/tools/ci/build-release.sh -a$ESP32_GITHUB_TOKEN - before_deploy: git submodule update --init - deploy: - - provider: script - skip_cleanup: true - script: bash $TRAVIS_BUILD_DIR/tools/ci/deploy-release.sh -t$TRAVIS_TAG -a$ESP32_GITHUB_TOKEN -s$TRAVIS_REPO_SLUG -drelease - on: - tags: true + script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 1 notifications: email: diff --git a/README.md b/README.md index d75a71b517e..76c15971a0b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# Arduino core for ESP32 WiFi chip [![Build Status](https://travis-ci.org/espressif/arduino-esp32.svg?branch=master)](https://travis-ci.org/espressif/arduino-esp32) +# Arduino core for the ESP32 +[![Build Status](https://travis-ci.org/espressif/arduino-esp32.svg?branch=master)](https://travis-ci.org/espressif/arduino-esp32) ![](https://github.com/espressif/arduino-esp32/workflows/ESP32%20Arduino%20CI/badge.svg) ### Need help or have a question? Join the chat at [![https://gitter.im/espressif/arduino-esp32](https://badges.gitter.im/espressif/arduino-esp32.svg)](https://gitter.im/espressif/arduino-esp32?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) @@ -9,17 +10,12 @@ - [Issue/Bug report template](#issuebug-report-template) - [ESP32Dev Board PINMAP](#esp32dev-board-pinmap) -## Development Status +### Development Status [Latest stable release ![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg?style=plastic) ![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) [Latest development release ![Development Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg?style=plastic) ![Development Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) ![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg?style=plastic) -Most of the framework is implemented. Most noticeable is the missing analogWrite. While analogWrite is on it's way, there are a few other options that you can use: -- 16 channels [LEDC](cores/esp32/esp32-hal-ledc.h) which is PWM -- 8 channels [SigmaDelta](cores/esp32/esp32-hal-sigmadelta.h) which uses SigmaDelta modulation -- 2 channels [DAC](cores/esp32/esp32-hal-dac.h) which gives real analog output - -## Installation Instructions +### Installation Instructions - Using Arduino IDE Boards Manager (preferred) + [Instructions for Boards Manager](docs/arduino-ide/boards_manager.md) - Using Arduino IDE with the development repository @@ -33,20 +29,19 @@ Most of the framework is implemented. Most noticeable is the missing analogWrite - [Using as ESP-IDF component](docs/esp-idf_component.md) - [Using OTAWebUpdater](docs/OTAWebUpdate/OTAWebUpdate.md) -#### Decoding exceptions +### Decoding exceptions You can use [EspExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder) to get meaningful call trace. -#### Issue/Bug report template +### Issue/Bug report template Before reporting an issue, make sure you've searched for similar one that was already created. Also make sure to go through all the issues labelled as [for reference](https://github.com/espressif/arduino-esp32/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3A%22for%20reference%22%20). Finally, if you're sure no one else had the issue, follow the [ISSUE_TEMPLATE](docs/ISSUE_TEMPLATE.md) while reporting any issue. - -## ESP32Dev Board PINMAP +### ESP32Dev Board PINMAP ![Pin Functions](docs/esp32_pinmap.png) -## Hint +### Hint Sometimes to program ESP32 via serial you must keep GPIO0 LOW during the programming process diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 62bdcce8883..00000000000 --- a/appveyor.yml +++ /dev/null @@ -1,19 +0,0 @@ -build: off -environment: - - matrix: - - PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClient" - - PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClientBasic" - - PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClientEvents" - - PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiIPv6" - - PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiScan" - - PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiSmartConfig" - -install: - - cmd: git submodule update --init --recursive - - cmd: SET PATH=%PATH%;C:\Python27\Scripts - - cmd: pip install -U https://github.com/platformio/platformio/archive/develop.zip - - cmd: platformio platform install https://github.com/platformio/platform-espressif32.git#feature/stage - -test_script: - - cmd: platformio ci -b esp32dev -b nano32 -b node32s diff --git a/boards.txt b/boards.txt index 1bd216ec70f..b14adc63d36 100644 --- a/boards.txt +++ b/boards.txt @@ -173,19 +173,34 @@ esp32wrover.build.boot=dio esp32wrover.build.partitions=default esp32wrover.build.defines=-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -esp32wrover.menu.PartitionScheme.default=Default +esp32wrover.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) esp32wrover.menu.PartitionScheme.default.build.partitions=default -esp32wrover.menu.PartitionScheme.minimal=Minimal (2MB FLASH) +esp32wrover.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +esp32wrover.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +esp32wrover.menu.PartitionScheme.default_8MB=8M Flash (3MB APP/1.5MB FAT) +esp32wrover.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +esp32wrover.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) esp32wrover.menu.PartitionScheme.minimal.build.partitions=minimal -esp32wrover.menu.PartitionScheme.no_ota=No OTA (Large APP) +esp32wrover.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) esp32wrover.menu.PartitionScheme.no_ota.build.partitions=no_ota esp32wrover.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 -esp32wrover.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA) +esp32wrover.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +esp32wrover.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +esp32wrover.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +esp32wrover.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +esp32wrover.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +esp32wrover.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +esp32wrover.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +esp32wrover.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +esp32wrover.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +esp32wrover.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) esp32wrover.menu.PartitionScheme.huge_app.build.partitions=huge_app esp32wrover.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 -esp32wrover.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA) +esp32wrover.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) esp32wrover.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs esp32wrover.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +esp32wrover.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FAT) +esp32wrover.menu.PartitionScheme.fatflash.build.partitions=ffat esp32wrover.menu.FlashMode.qio=QIO esp32wrover.menu.FlashMode.qio.build.flash_mode=dio @@ -257,6 +272,15 @@ pico32.build.boot=dio pico32.build.partitions=default pico32.build.defines= +pico32.menu.PartitionScheme.default=Default +pico32.menu.PartitionScheme.default.build.partitions=default +pico32.menu.PartitionScheme.no_ota=No OTA (Large APP) +pico32.menu.PartitionScheme.no_ota.build.partitions=no_ota +pico32.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +pico32.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA) +pico32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +pico32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + pico32.menu.UploadSpeed.921600=921600 pico32.menu.UploadSpeed.921600.upload.speed=921600 pico32.menu.UploadSpeed.115200=115200 @@ -1654,6 +1678,15 @@ featheresp32.menu.DebugLevel.debug.build.code_debug=4 featheresp32.menu.DebugLevel.verbose=Verbose featheresp32.menu.DebugLevel.verbose.build.code_debug=5 +featheresp32.menu.PartitionScheme.default=Default +featheresp32.menu.PartitionScheme.default.build.partitions=default +featheresp32.menu.PartitionScheme.no_ota=No OTA (Large APP) +featheresp32.menu.PartitionScheme.no_ota.build.partitions=no_ota +featheresp32.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +featheresp32.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA) +featheresp32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +featheresp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 + ############################################################## nodemcu-32s.name=NodeMCU-32S @@ -4127,3 +4160,60 @@ gpy.menu.DebugLevel.verbose.build.code_debug=5 ############################################################## +vintlabs-devkit-v1.name=VintLabs ESP32 Devkit + +vintlabs-devkit-v1.upload.tool=esptool_py +vintlabs-devkit-v1.upload.maximum_size=1310720 +vintlabs-devkit-v1.upload.maximum_data_size=327680 +vintlabs-devkit-v1.upload.wait_for_upload_port=true + +vintlabs-devkit-v1.serial.disableDTR=true +vintlabs-devkit-v1.serial.disableRTS=true + +vintlabs-devkit-v1.build.mcu=esp32 +vintlabs-devkit-v1.build.core=esp32 +vintlabs-devkit-v1.build.variant=vintlabsdevkitv1 +vintlabs-devkit-v1.build.board=ESP32_DEV + +vintlabs-devkit-v1.build.f_cpu=240000000L +vintlabs-devkit-v1.build.flash_mode=dio +vintlabs-devkit-v1.build.flash_size=4MB +vintlabs-devkit-v1.build.boot=dio +vintlabs-devkit-v1.build.partitions=default +vintlabs-devkit-v1.build.defines= + +vintlabs-devkit-v1.menu.FlashFreq.80=80MHz +vintlabs-devkit-v1.menu.FlashFreq.80.build.flash_freq=80m +vintlabs-devkit-v1.menu.FlashFreq.40=40MHz +vintlabs-devkit-v1.menu.FlashFreq.40.build.flash_freq=40m + +vintlabs-devkit-v1.menu.UploadSpeed.2000000=2000000 +vintlabs-devkit-v1.menu.UploadSpeed.2000000.upload.speed=2000000 +vintlabs-devkit-v1.menu.UploadSpeed.921600=921600 +vintlabs-devkit-v1.menu.UploadSpeed.921600.upload.speed=921600 +vintlabs-devkit-v1.menu.UploadSpeed.115200=115200 +vintlabs-devkit-v1.menu.UploadSpeed.115200.upload.speed=115200 +vintlabs-devkit-v1.menu.UploadSpeed.256000.windows=256000 +vintlabs-devkit-v1.menu.UploadSpeed.256000.upload.speed=256000 +vintlabs-devkit-v1.menu.UploadSpeed.230400.windows.upload.speed=256000 +vintlabs-devkit-v1.menu.UploadSpeed.230400=230400 +vintlabs-devkit-v1.menu.UploadSpeed.230400.upload.speed=230400 +vintlabs-devkit-v1.menu.UploadSpeed.460800.linux=460800 +vintlabs-devkit-v1.menu.UploadSpeed.460800.macosx=460800 +vintlabs-devkit-v1.menu.UploadSpeed.460800.upload.speed=460800 +vintlabs-devkit-v1.menu.UploadSpeed.512000.windows=512000 +vintlabs-devkit-v1.menu.UploadSpeed.512000.upload.speed=512000 + +vintlabs-devkit-v1.menu.DebugLevel.none=None +vintlabs-devkit-v1.menu.DebugLevel.none.build.code_debug=0 +vintlabs-devkit-v1.menu.DebugLevel.error=Error +vintlabs-devkit-v1.menu.DebugLevel.error.build.code_debug=1 +vintlabs-devkit-v1.menu.DebugLevel.warn=Warn +vintlabs-devkit-v1.menu.DebugLevel.warn.build.code_debug=2 +vintlabs-devkit-v1.menu.DebugLevel.info=Info +vintlabs-devkit-v1.menu.DebugLevel.info.build.code_debug=3 +vintlabs-devkit-v1.menu.DebugLevel.debug=Debug +vintlabs-devkit-v1.menu.DebugLevel.debug.build.code_debug=4 + +############################################################## + diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index 89eacf85d0e..5f886650816 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -97,10 +97,12 @@ class HardwareSerial: public Stream uart_t* _uart; }; +extern void serialEventRun(void) __attribute__((weak)); + #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) extern HardwareSerial Serial; extern HardwareSerial Serial1; extern HardwareSerial Serial2; #endif -#endif +#endif // HardwareSerial_h diff --git a/cores/esp32/base64.cpp b/cores/esp32/base64.cpp index e7ba3fadbec..1fc144e2659 100644 --- a/cores/esp32/base64.cpp +++ b/cores/esp32/base64.cpp @@ -31,11 +31,11 @@ extern "C" { /** * convert input data to base64 - * @param data uint8_t * + * @param data const uint8_t * * @param length size_t * @return String */ -String base64::encode(uint8_t * data, size_t length) +String base64::encode(const uint8_t * data, size_t length) { size_t size = base64_encode_expected_len(length) + 1; char * buffer = (char *) malloc(size); @@ -54,10 +54,10 @@ String base64::encode(uint8_t * data, size_t length) /** * convert input data to base64 - * @param text String + * @param text const String& * @return String */ -String base64::encode(String text) +String base64::encode(const String& text) { return base64::encode((uint8_t *) text.c_str(), text.length()); } diff --git a/cores/esp32/base64.h b/cores/esp32/base64.h index 8e6726a35d7..97095817b8f 100644 --- a/cores/esp32/base64.h +++ b/cores/esp32/base64.h @@ -4,8 +4,8 @@ class base64 { public: - static String encode(uint8_t * data, size_t length); - static String encode(String text); + static String encode(const uint8_t * data, size_t length); + static String encode(const String& text); private: }; diff --git a/cores/esp32/esp32-hal-misc.c b/cores/esp32/esp32-hal-misc.c index ae06edc3378..be08e4b7313 100644 --- a/cores/esp32/esp32-hal-misc.c +++ b/cores/esp32/esp32-hal-misc.c @@ -44,11 +44,13 @@ float temperatureRead() return (temprature_sens_read() - 32) / 1.8; } -void yield() +void __yield() { vPortYield(); } +void yield() __attribute__ ((weak, alias("__yield"))); + #if CONFIG_AUTOSTART_ARDUINO extern TaskHandle_t loopTaskHandle; diff --git a/cores/esp32/esp32-hal-timer.c b/cores/esp32/esp32-hal-timer.c index c6b7fbf5d97..ed804d4e348 100644 --- a/cores/esp32/esp32-hal-timer.c +++ b/cores/esp32/esp32-hal-timer.c @@ -165,6 +165,7 @@ void timerStop(hw_timer_t *timer){ void timerRestart(hw_timer_t *timer){ timer->dev->config.enable = 0; + timer->dev->reload = 1; timer->dev->config.enable = 1; } diff --git a/cores/esp32/main.cpp b/cores/esp32/main.cpp index 3a455c8a878..41f1985b94c 100644 --- a/cores/esp32/main.cpp +++ b/cores/esp32/main.cpp @@ -17,6 +17,7 @@ void loopTask(void *pvParameters) esp_task_wdt_reset(); } loop(); + if (serialEventRun) serialEventRun(); } } diff --git a/docs/arduino-ide/boards_manager.md b/docs/arduino-ide/boards_manager.md index 9161ba6ff3e..59428b9c3eb 100644 --- a/docs/arduino-ide/boards_manager.md +++ b/docs/arduino-ide/boards_manager.md @@ -1,13 +1,12 @@ -Installation instructions using Arduino IDE Boards Manager -========================================================== +## Installation instructions using Arduino IDE Boards Manager +### ========================================================== -Starting with 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, Mac OS, and Linux (32 and 64 bit). +- Stable release link: `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json` +- Development release link: `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json` + +Starting with 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, Mac OS, and Linux (32, 64 bit and ARM). - Install the current upstream Arduino IDE at the 1.8 level or later. The current version is at the [Arduino website](http://www.arduino.cc/en/main/software). - Start Arduino and open Preferences window. -- Enter ```https://dl.espressif.com/dl/package_esp32_index.json``` into *Additional Board Manager URLs* field. You can add multiple URLs, separating them with commas. +- Enter one of the release links above into *Additional Board Manager URLs* field. You can add multiple URLs, separating them with commas. - Open Boards Manager from Tools > Board menu and install *esp32* platform (and don't forget to select your ESP32 board from Tools > Board menu after installation). - -Stable release link: `https://dl.espressif.com/dl/package_esp32_index.json` - -Development release link: `https://dl.espressif.com/dl/package_esp32_dev_index.json` diff --git a/libraries/BLE/examples/BLE_client/BLE_client.ino b/libraries/BLE/examples/BLE_client/BLE_client.ino index 4c58299e746..8950075ce5b 100644 --- a/libraries/BLE/examples/BLE_client/BLE_client.ino +++ b/libraries/BLE/examples/BLE_client/BLE_client.ino @@ -87,6 +87,7 @@ bool connectToServer() { pRemoteCharacteristic->registerForNotify(notifyCallback); connected = true; + return true; } /** * Scan for BLE servers and find the first one that advertises the service we are looking for. diff --git a/libraries/BLE/src/BLECharacteristic.cpp b/libraries/BLE/src/BLECharacteristic.cpp index 11636921b77..25146136184 100644 --- a/libraries/BLE/src/BLECharacteristic.cpp +++ b/libraries/BLE/src/BLECharacteristic.cpp @@ -693,15 +693,13 @@ void BLECharacteristic::setValue(int& data32) { } // setValue void BLECharacteristic::setValue(float& data32) { - uint8_t temp[4]; - *((float*)temp) = data32; - setValue(temp, 4); + float temp = data32; + setValue((uint8_t*)&temp, 4); } // setValue void BLECharacteristic::setValue(double& data64) { - uint8_t temp[8]; - *((double*)temp) = data64; - setValue(temp, 8); + double temp = data64; + setValue((uint8_t*)&temp, 8); } // setValue diff --git a/libraries/BLE/src/BLEDevice.cpp b/libraries/BLE/src/BLEDevice.cpp index db45d07bd13..d828b4e1946 100644 --- a/libraries/BLE/src/BLEDevice.cpp +++ b/libraries/BLE/src/BLEDevice.cpp @@ -32,14 +32,8 @@ #include "esp32-hal-bt.h" #endif -#if defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char* LOG_TAG = "BLEDevice"; -#endif - /** * Singletons for the BLEDevice. @@ -625,7 +619,7 @@ void BLEDevice::removePeerDevice(uint16_t conn_id, bool _client) { esp_bluedroid_deinit(); esp_bt_controller_disable(); esp_bt_controller_deinit(); -#ifndef ARDUINO_ARCH_ESP32 +#ifdef ARDUINO_ARCH_ESP32 if (release_memory) { esp_bt_controller_mem_release(ESP_BT_MODE_BTDM); // <-- require tests because we released classic BT memory and this can cause crash (most likely not, esp-idf takes care of it) } else { diff --git a/libraries/BLE/src/BLERemoteCharacteristic.cpp b/libraries/BLE/src/BLERemoteCharacteristic.cpp index 840076f8f2f..fe4559199bd 100644 --- a/libraries/BLE/src/BLERemoteCharacteristic.cpp +++ b/libraries/BLE/src/BLERemoteCharacteristic.cpp @@ -389,6 +389,17 @@ uint8_t BLERemoteCharacteristic::readUInt8() { return 0; } // readUInt8 +/** + * @brief Read a float value. + * @return the float value. + */ +float BLERemoteCharacteristic::readFloat() { + std::string value = readValue(); + if (value.length() >= 4) { + return *(float*)(value.data()); + } + return 0.0; +} // readFloat /** * @brief Read the value of the remote characteristic. diff --git a/libraries/BLE/src/BLERemoteCharacteristic.h b/libraries/BLE/src/BLERemoteCharacteristic.h index fbcafe8d306..1d0db1c379d 100644 --- a/libraries/BLE/src/BLERemoteCharacteristic.h +++ b/libraries/BLE/src/BLERemoteCharacteristic.h @@ -45,6 +45,7 @@ class BLERemoteCharacteristic { uint8_t readUInt8(); uint16_t readUInt16(); uint32_t readUInt32(); + float readFloat(); void registerForNotify(notify_callback _callback, bool notifications = true); void writeValue(uint8_t* data, size_t length, bool response = false); void writeValue(std::string newValue, bool response = false); diff --git a/libraries/BLE/src/BLERemoteService.cpp b/libraries/BLE/src/BLERemoteService.cpp index 754e8ac22d5..278e9c1cab4 100644 --- a/libraries/BLE/src/BLERemoteService.cpp +++ b/libraries/BLE/src/BLERemoteService.cpp @@ -226,6 +226,20 @@ std::map* BLERemoteService::getCharacteri return &m_characteristicMap; } // getCharacteristics +/** + * @brief Retrieve a map of all the characteristics of this service. + * @return A map of all the characteristics of this service. + */ +std::map* BLERemoteService::getCharacteristicsByHandle() { + // If is possible that we have not read the characteristics associated with the service so do that + // now. The request to retrieve the characteristics by calling "retrieveCharacteristics" is a blocking + // call and does not return until all the characteristics are available. + if (!m_haveCharacteristics) { + retrieveCharacteristics(); + } + return &m_characteristicMapByHandle; +} // getCharacteristicsByHandle + /** * @brief This function is designed to get characteristics map when we have multiple characteristics with the same UUID */ diff --git a/libraries/BLE/src/BLEUUID.cpp b/libraries/BLE/src/BLEUUID.cpp index a1ec2148df5..1a9473678b2 100644 --- a/libraries/BLE/src/BLEUUID.cpp +++ b/libraries/BLE/src/BLEUUID.cpp @@ -352,8 +352,8 @@ std::string BLEUUID::toString() { // If the UUIDs are 16 or 32 bit, pad correctly. if (m_uuid.len == ESP_UUID_LEN_16) { // If the UUID is 16bit, pad correctly. - char hex[5]; - snprintf(hex, sizeof(hex), "%04x", m_uuid.uuid.uuid16); + char hex[9]; + snprintf(hex, sizeof(hex), "%08x", m_uuid.uuid.uuid16); return std::string(hex) + "-0000-1000-8000-00805f9b34fb"; } // End 16bit UUID @@ -367,7 +367,7 @@ std::string BLEUUID::toString() { // // UUID string format: // AABBCCDD-EEFF-GGHH-IIJJ-KKLLMMNNOOPP - auto size = 35; + auto size = 37; // 32 for UUID data, 4 for '-' delimiters and one for a terminator == 37 chars char *hex = (char *)malloc(size); snprintf(hex, size, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", m_uuid.uuid.uuid128[15], m_uuid.uuid.uuid128[14], diff --git a/libraries/BLE/src/GeneralUtils.cpp b/libraries/BLE/src/GeneralUtils.cpp index 1c62af9391c..02736b81b1a 100644 --- a/libraries/BLE/src/GeneralUtils.cpp +++ b/libraries/BLE/src/GeneralUtils.cpp @@ -104,11 +104,10 @@ bool GeneralUtils::base64Encode(const std::string& in, std::string* out) { * * Amount of free RAM */ void GeneralUtils::dumpInfo() { - size_t freeHeap = heap_caps_get_free_size(MALLOC_CAP_8BIT); esp_chip_info_t chipInfo; esp_chip_info(&chipInfo); log_v("--- dumpInfo ---"); - log_v("Free heap: %d", freeHeap); + log_v("Free heap: %d", heap_caps_get_free_size(MALLOC_CAP_8BIT)); log_v("Chip Info: Model: %d, cores: %d, revision: %d", chipInfo.model, chipInfo.cores, chipInfo.revision); log_v("ESP-IDF version: %s", esp_get_idf_version()); log_v("---"); diff --git a/libraries/BluetoothSerial/examples/SerialToSerialBTM/SerialToSerialBTM.ino b/libraries/BluetoothSerial/examples/SerialToSerialBTM/SerialToSerialBTM.ino new file mode 100644 index 00000000000..73f3dc058b4 --- /dev/null +++ b/libraries/BluetoothSerial/examples/SerialToSerialBTM/SerialToSerialBTM.ino @@ -0,0 +1,56 @@ +//This example code is in the Public Domain (or CC0 licensed, at your option.) +//By Victor Tchistiak - 2019 +// +//This example demostrates master mode bluetooth connection and pin +//it creates a bridge between Serial and Classical Bluetooth (SPP) +//this is an extention of the SerialToSerialBT example by Evandro Copercini - 2018 +// + +#include "BluetoothSerial.h" + +BluetoothSerial SerialBT; + +String MACadd = "AA:BB:CC:11:22:33"; +uint8_t address[6] = {0xAA, 0xBB, 0xCC, 0x11, 0x22, 0x33}; +//uint8_t address[6] = {0x00, 0x1D, 0xA5, 0x02, 0xC3, 0x22}; +String name = "OBDII"; +char *pin = "1234"; //<- standard pin would be provided by default +bool connected; + +void setup() { + Serial.begin(115200); + //SerialBT.setPin(pin); + SerialBT.begin("ESP32test", true); + //SerialBT.setPin(pin); + Serial.println("The device started in master mode, make sure remote BT device is on!"); + + // connect(address) is fast (upto 10 secs max), connect(name) is slow (upto 30 secs max) as it needs + // to resolve name to address first, but it allows to connect to different devices with the same name. + // Set CoreDebugLevel to Info to view devices bluetooth address and device names + connected = SerialBT.connect(name); + //connected = SerialBT.connect(address); + + if(connected) { + Serial.println("Connected Succesfully!"); + } else { + while(!SerialBT.connected(10000)) { + Serial.println("Failed to connect. Make sure remote device is available and in range, then restart app."); + } + } + // disconnect() may take upto 10 secs max + if (SerialBT.disconnect()) { + Serial.println("Disconnected Succesfully!"); + } + // this would reconnect to the name(will use address, if resolved) or address used with connect(name/address). + SerialBT.connect(); +} + +void loop() { + if (Serial.available()) { + SerialBT.write(Serial.read()); + } + if (SerialBT.available()) { + Serial.write(SerialBT.read()); + } + delay(20); +} diff --git a/libraries/BluetoothSerial/examples/bt_remove_paired_devices/bt_remove_paired_devices.ino b/libraries/BluetoothSerial/examples/bt_remove_paired_devices/bt_remove_paired_devices.ino new file mode 100755 index 00000000000..c316a73b2bc --- /dev/null +++ b/libraries/BluetoothSerial/examples/bt_remove_paired_devices/bt_remove_paired_devices.ino @@ -0,0 +1,87 @@ +//This example code is in the Public Domain (or CC0 licensed, at your option.) +//By Victor Tchistiak - 2019 +// +//This example demonstrates reading and removing paired devices stored on the ESP32 flash memory +//Sometimes you may find your ESP32 device could not connect to the remote device despite +//many successful connections earlier. This is most likely a result of client replacing your paired +//device info with new one from other device. The BT clients store connection info for paired devices, +//but it is limited to a few devices only. When new device pairs and number of stored devices is exceeded, +//one of the previously paired devices would be replaced with new one. +//The only remedy is to delete this saved bound device from your device flash memory +//and pair with the other device again. +// +#include "esp_bt_main.h" +#include "esp_bt_device.h" +#include"esp_gap_bt_api.h" +#include "esp_err.h" + +#define REMOVE_BONDED_DEVICES 0 // <- Set to 0 to view all bonded devices addresses, set to 1 to remove + +#define PAIR_MAX_DEVICES 20 +uint8_t pairedDeviceBtAddr[PAIR_MAX_DEVICES][6]; +char bda_str[18]; + +bool initBluetooth() +{ + if(!btStart()) { + Serial.println("Failed to initialize controller"); + return false; + } + + if(esp_bluedroid_init() != ESP_OK) { + Serial.println("Failed to initialize bluedroid"); + return false; + } + + if(esp_bluedroid_enable() != ESP_OK) { + Serial.println("Failed to enable bluedroid"); + return false; + } + return true; +} + +char *bda2str(const uint8_t* bda, char *str, size_t size) +{ + if (bda == NULL || str == NULL || size < 18) { + return NULL; + } + sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", + bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + return str; +} + +void setup() { + Serial.begin(115200); + + initBluetooth(); + Serial.print("ESP32 bluetooth address: "); Serial.println(bda2str(esp_bt_dev_get_address(), bda_str, 18)); + // Get the numbers of bonded/paired devices in the BT module + int count = esp_bt_gap_get_bond_device_num(); + if(!count) { + Serial.println("No bonded device found."); + } else { + Serial.print("Bonded device count: "); Serial.println(count); + if(PAIR_MAX_DEVICES < count) { + count = PAIR_MAX_DEVICES; + Serial.print("Reset bonded device count: "); Serial.println(count); + } + esp_err_t tError = esp_bt_gap_get_bond_device_list(&count, pairedDeviceBtAddr); + if(ESP_OK == tError) { + for(int i = 0; i < count; i++) { + Serial.print("Found bonded device # "); Serial.print(i); Serial.print(" -> "); + Serial.println(bda2str(pairedDeviceBtAddr[i], bda_str, 18)); + if(REMOVE_BONDED_DEVICES) { + esp_err_t tError = esp_bt_gap_remove_bond_device(pairedDeviceBtAddr[i]); + if(ESP_OK == tError) { + Serial.print("Removed bonded device # "); + } else { + Serial.print("Failed to remove bonded device # "); + } + Serial.println(i); + } + } + } + } +} + +void loop() {} diff --git a/libraries/BluetoothSerial/src/BluetoothSerial.cpp b/libraries/BluetoothSerial/src/BluetoothSerial.cpp old mode 100644 new mode 100755 index a8332b8bc99..612ddd59a99 --- a/libraries/BluetoothSerial/src/BluetoothSerial.cpp +++ b/libraries/BluetoothSerial/src/BluetoothSerial.cpp @@ -53,15 +53,82 @@ static EventGroupHandle_t _spp_event_group = NULL; static boolean secondConnectionAttempt; static esp_spp_cb_t * custom_spp_callback = NULL; +#define INQ_LEN 0x10 +#define INQ_NUM_RSPS 20 +#define READY_TIMEOUT (10 * 1000) +#define SCAN_TIMEOUT (INQ_LEN * 2 * 1000) +static esp_bd_addr_t _peer_bd_addr; +static char _remote_name[ESP_BT_GAP_MAX_BDNAME_LEN + 1]; +static bool _isRemoteAddressSet; +static bool _isMaster; +static esp_bt_pin_code_t _pin_code; +static int _pin_len; +static bool _isPinSet; +static bool _enableSSP; + #define SPP_RUNNING 0x01 #define SPP_CONNECTED 0x02 #define SPP_CONGESTED 0x04 +#define SPP_DISCONNECTED 0x08 typedef struct { size_t len; uint8_t data[]; } spp_packet_t; +#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) +static char *bda2str(esp_bd_addr_t bda, char *str, size_t size) +{ + if (bda == NULL || str == NULL || size < 18) { + return NULL; + } + + uint8_t *p = bda; + sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", + p[0], p[1], p[2], p[3], p[4], p[5]); + return str; +} +#endif + +static bool get_name_from_eir(uint8_t *eir, char *bdname, uint8_t *bdname_len) +{ + if (!eir || !bdname || !bdname_len) { + return false; + } + + uint8_t *rmt_bdname, rmt_bdname_len; + *bdname = *bdname_len = rmt_bdname_len = 0; + + rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME, &rmt_bdname_len); + if (!rmt_bdname) { + rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &rmt_bdname_len); + } + if (rmt_bdname) { + rmt_bdname_len = rmt_bdname_len > ESP_BT_GAP_MAX_BDNAME_LEN ? ESP_BT_GAP_MAX_BDNAME_LEN : rmt_bdname_len; + memcpy(bdname, rmt_bdname, rmt_bdname_len); + bdname[rmt_bdname_len] = 0; + *bdname_len = rmt_bdname_len; + return true; + } + return false; +} + +static bool btSetPin() { + esp_bt_pin_type_t pin_type; + if (_isPinSet) { + if (_pin_len) { + log_i("pin set"); + pin_type = ESP_BT_PIN_TYPE_FIXED; + } else { + _isPinSet = false; + log_i("pin reset"); + pin_type = ESP_BT_PIN_TYPE_VARIABLE; // pin_code would be ignored (default) + } + return (esp_bt_gap_set_pin(pin_type, _pin_len, _pin_code) == ESP_OK); + } + return false; +} + static esp_err_t _spp_queue_packet(uint8_t *data, size_t len){ if(!data || !len){ log_w("No data provided"); @@ -136,12 +203,12 @@ static void _spp_tx_task(void * arg){ if(len){ memcpy(_spp_tx_buffer, data, len); _spp_tx_buffer_len += len; - free(packet); - packet = NULL; if(uxQueueMessagesWaiting(_spp_tx_queue) == 0){ _spp_send_buffer(); } } + free(packet); + packet = NULL; } } else { log_e("Something went horribly wrong"); @@ -159,29 +226,34 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) case ESP_SPP_INIT_EVT: log_i("ESP_SPP_INIT_EVT"); esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); - esp_spp_start_srv(ESP_SPP_SEC_NONE, ESP_SPP_ROLE_SLAVE, 0, _spp_server_name); + if (!_isMaster) { + log_i("ESP_SPP_INIT_EVT: slave: start"); + esp_spp_start_srv(ESP_SPP_SEC_NONE, ESP_SPP_ROLE_SLAVE, 0, _spp_server_name); + } xEventGroupSetBits(_spp_event_group, SPP_RUNNING); break; case ESP_SPP_SRV_OPEN_EVT://Server connection open + log_i("ESP_SPP_SRV_OPEN_EVT"); if (!_spp_client){ _spp_client = param->open.handle; } else { secondConnectionAttempt = true; esp_spp_disconnect(param->open.handle); } + xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED); xEventGroupSetBits(_spp_event_group, SPP_CONNECTED); - log_i("ESP_SPP_SRV_OPEN_EVT"); break; case ESP_SPP_CLOSE_EVT://Client connection closed + log_i("ESP_SPP_CLOSE_EVT"); if(secondConnectionAttempt) { secondConnectionAttempt = false; } else { _spp_client = 0; - } + xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED); + } xEventGroupClearBits(_spp_event_group, SPP_CONNECTED); - log_i("ESP_SPP_CLOSE_EVT"); break; case ESP_SPP_CONG_EVT://connection congestion status changed @@ -216,25 +288,151 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) } break; - //should maybe delete those. case ESP_SPP_DISCOVERY_COMP_EVT://discovery complete log_i("ESP_SPP_DISCOVERY_COMP_EVT"); + if (param->disc_comp.status == ESP_SPP_SUCCESS) { + log_i("ESP_SPP_DISCOVERY_COMP_EVT: spp connect to remote"); + esp_spp_connect(ESP_SPP_SEC_AUTHENTICATE, ESP_SPP_ROLE_MASTER, param->disc_comp.scn[0], _peer_bd_addr); + } break; + case ESP_SPP_OPEN_EVT://Client connection open log_i("ESP_SPP_OPEN_EVT"); + if (!_spp_client){ + _spp_client = param->open.handle; + } else { + secondConnectionAttempt = true; + esp_spp_disconnect(param->open.handle); + } + xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED); + xEventGroupSetBits(_spp_event_group, SPP_CONNECTED); break; + case ESP_SPP_START_EVT://server started log_i("ESP_SPP_START_EVT"); break; + case ESP_SPP_CL_INIT_EVT://client initiated a connection log_i("ESP_SPP_CL_INIT_EVT"); break; + default: break; } if(custom_spp_callback)(*custom_spp_callback)(event, param); } +static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) +{ + switch(event){ + case ESP_BT_GAP_DISC_RES_EVT: + log_i("ESP_BT_GAP_DISC_RES_EVT"); +#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) + char bda_str[18]; + log_i("Scanned device: %s", bda2str(param->disc_res.bda, bda_str, 18)); +#endif + for (int i = 0; i < param->disc_res.num_prop; i++) { + uint8_t peer_bdname_len; + char peer_bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1]; + switch(param->disc_res.prop[i].type) { + case ESP_BT_GAP_DEV_PROP_EIR: + if (get_name_from_eir((uint8_t*)param->disc_res.prop[i].val, peer_bdname, &peer_bdname_len)) { + log_i("ESP_BT_GAP_DISC_RES_EVT : EIR : %s : %d", peer_bdname, peer_bdname_len); + if (strlen(_remote_name) == peer_bdname_len + && strncmp(peer_bdname, _remote_name, peer_bdname_len) == 0) { + log_v("ESP_BT_GAP_DISC_RES_EVT : SPP_START_DISCOVERY_EIR : %s", peer_bdname, peer_bdname_len); + _isRemoteAddressSet = true; + memcpy(_peer_bd_addr, param->disc_res.bda, ESP_BD_ADDR_LEN); + esp_bt_gap_cancel_discovery(); + esp_spp_start_discovery(_peer_bd_addr); + } + } + break; + + case ESP_BT_GAP_DEV_PROP_BDNAME: + peer_bdname_len = param->disc_res.prop[i].len; + memcpy(peer_bdname, param->disc_res.prop[i].val, peer_bdname_len); + peer_bdname_len--; // len includes 0 terminator + log_v("ESP_BT_GAP_DISC_RES_EVT : BDNAME : %s : %d", peer_bdname, peer_bdname_len); + if (strlen(_remote_name) == peer_bdname_len + && strncmp(peer_bdname, _remote_name, peer_bdname_len) == 0) { + log_i("ESP_BT_GAP_DISC_RES_EVT : SPP_START_DISCOVERY_BDNAME : %s", peer_bdname); + _isRemoteAddressSet = true; + memcpy(_peer_bd_addr, param->disc_res.bda, ESP_BD_ADDR_LEN); + esp_bt_gap_cancel_discovery(); + esp_spp_start_discovery(_peer_bd_addr); + } + break; + + case ESP_BT_GAP_DEV_PROP_COD: + //log_i("ESP_BT_GAP_DEV_PROP_COD"); + break; + + case ESP_BT_GAP_DEV_PROP_RSSI: + //log_i("ESP_BT_GAP_DEV_PROP_RSSI"); + break; + + default: + break; + } + if (_isRemoteAddressSet) + break; + } + break; + case ESP_BT_GAP_DISC_STATE_CHANGED_EVT: + log_i("ESP_BT_GAP_DISC_STATE_CHANGED_EVT"); + break; + + case ESP_BT_GAP_RMT_SRVCS_EVT: + log_i( "ESP_BT_GAP_RMT_SRVCS_EVT"); + break; + + case ESP_BT_GAP_RMT_SRVC_REC_EVT: + log_i("ESP_BT_GAP_RMT_SRVC_REC_EVT"); + break; + + case ESP_BT_GAP_AUTH_CMPL_EVT: + if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { + log_v("authentication success: %s", param->auth_cmpl.device_name); + } else { + log_e("authentication failed, status:%d", param->auth_cmpl.stat); + } + break; + + case ESP_BT_GAP_PIN_REQ_EVT: + // default pairing pins + log_i("ESP_BT_GAP_PIN_REQ_EVT min_16_digit:%d", param->pin_req.min_16_digit); + if (param->pin_req.min_16_digit) { + log_i("Input pin code: 0000 0000 0000 0000"); + esp_bt_pin_code_t pin_code; + memset(pin_code, '0', ESP_BT_PIN_CODE_LEN); + esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code); + } else { + log_i("Input pin code: 1234"); + esp_bt_pin_code_t pin_code; + memcpy(pin_code, "1234", 4); + esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code); + } + break; + + case ESP_BT_GAP_CFM_REQ_EVT: + log_i("ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); + esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); + break; + + case ESP_BT_GAP_KEY_NOTIF_EVT: + log_i("ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey); + break; + + case ESP_BT_GAP_KEY_REQ_EVT: + log_i("ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); + break; + + default: + break; + } +} + static bool _init_bt(const char *deviceName) { if(!_spp_event_group){ @@ -245,6 +443,7 @@ static bool _init_bt(const char *deviceName) } xEventGroupClearBits(_spp_event_group, 0xFFFFFF); xEventGroupSetBits(_spp_event_group, SPP_CONGESTED); + xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED); } if (_spp_rx_queue == NULL){ _spp_rx_queue = xQueueCreate(RX_QUEUE_SIZE, sizeof(uint8_t)); //initialize the queue @@ -297,6 +496,11 @@ static bool _init_bt(const char *deviceName) } } + if (_isMaster && esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) { + log_e("gap register failed"); + return false; + } + if (esp_spp_register_callback(esp_spp_cb) != ESP_OK){ log_e("spp register failed"); return false; @@ -307,8 +511,20 @@ static bool _init_bt(const char *deviceName) return false; } + log_i("device name set"); esp_bt_dev_set_device_name(deviceName); + if (_isPinSet) { + btSetPin(); + } + + if (_enableSSP) { + log_i("Simple Secure Pairing"); + esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; + esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO; + esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); + } + // the default BTA_DM_COD_LOUDSPEAKER does not work with the macOS BT stack esp_bt_cod_t cod; cod.major = 0b00001; @@ -318,7 +534,6 @@ static bool _init_bt(const char *deviceName) log_e("set cod failed"); return false; } - return true; } @@ -361,6 +576,11 @@ static bool _stop_bt() return true; } +static bool waitForConnect(int timeout) { + TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS; + return (xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED, pdFALSE, pdTRUE, xTicksToWait) != 0); +} + /* * Serial Bluetooth Arduino * @@ -376,8 +596,9 @@ BluetoothSerial::~BluetoothSerial(void) _stop_bt(); } -bool BluetoothSerial::begin(String localName) +bool BluetoothSerial::begin(String localName, bool isMaster) { + _isMaster = isMaster; if (localName.length()){ local_name = localName; } @@ -445,4 +666,129 @@ esp_err_t BluetoothSerial::register_callback(esp_spp_cb_t * callback) return ESP_OK; } +//Simple Secure Pairing +void BluetoothSerial::enableSSP() { + _enableSSP = true; +} +/* + * Set default parameters for Legacy Pairing + * Use fixed pin code +*/ +bool BluetoothSerial::setPin(const char *pin) { + bool isEmpty = !(pin && *pin); + if (isEmpty && !_isPinSet) { + return true; // nothing to do + } else if (!isEmpty){ + _pin_len = strlen(pin); + memcpy(_pin_code, pin, _pin_len); + } else { + _pin_len = 0; // resetting pin to none (default) + } + _pin_code[_pin_len] = 0; + _isPinSet = true; + if (isReady(false, READY_TIMEOUT)) { + btSetPin(); + } + return true; +} + +bool BluetoothSerial::connect(String remoteName) +{ + if (!isReady(true, READY_TIMEOUT)) return false; + if (remoteName && remoteName.length() < 1) { + log_e("No remote name is provided"); + return false; + } + disconnect(); + _isRemoteAddressSet = false; + strncpy(_remote_name, remoteName.c_str(), ESP_BT_GAP_MAX_BDNAME_LEN); + _remote_name[ESP_BT_GAP_MAX_BDNAME_LEN] = 0; + log_i("master : remoteName"); + // will first resolve name to address + esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); + if (esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, INQ_LEN, INQ_NUM_RSPS) == ESP_OK) { + return waitForConnect(SCAN_TIMEOUT); + } + return false; +} + +bool BluetoothSerial::connect(uint8_t remoteAddress[]) +{ + if (!isReady(true, READY_TIMEOUT)) return false; + if (!remoteAddress) { + log_e("No remote address is provided"); + return false; + } + disconnect(); + _remote_name[0] = 0; + _isRemoteAddressSet = true; + memcpy(_peer_bd_addr, remoteAddress, ESP_BD_ADDR_LEN); + log_i("master : remoteAddress"); + if (esp_spp_start_discovery(_peer_bd_addr) == ESP_OK) { + return waitForConnect(READY_TIMEOUT); + } + return false; +} + +bool BluetoothSerial::connect() +{ + if (!isReady(true, READY_TIMEOUT)) return false; + if (_isRemoteAddressSet){ + disconnect(); + // use resolved or set address first + log_i("master : remoteAddress"); + if (esp_spp_start_discovery(_peer_bd_addr) == ESP_OK) { + return waitForConnect(READY_TIMEOUT); + } + return false; + } else if (_remote_name[0]) { + disconnect(); + log_i("master : remoteName"); + // will resolve name to address first - it may take a while + esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); + if (esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, INQ_LEN, INQ_NUM_RSPS) == ESP_OK) { + return waitForConnect(SCAN_TIMEOUT); + } + return false; + } + log_e("Neither Remote name nor address was provided"); + return false; +} + +bool BluetoothSerial::disconnect() { + if (_spp_client) { + flush(); + log_i("disconnecting"); + if (esp_spp_disconnect(_spp_client) == ESP_OK) { + TickType_t xTicksToWait = READY_TIMEOUT / portTICK_PERIOD_MS; + return (xEventGroupWaitBits(_spp_event_group, SPP_DISCONNECTED, pdFALSE, pdTRUE, xTicksToWait) != 0); + } + } + return false; +} + +bool BluetoothSerial::unpairDevice(uint8_t remoteAddress[]) { + if (isReady(false, READY_TIMEOUT)) { + log_i("removing bonded device"); + return (esp_bt_gap_remove_bond_device(remoteAddress) == ESP_OK); + } + return false; +} + +bool BluetoothSerial::connected(int timeout) { + return waitForConnect(timeout); +} + +bool BluetoothSerial::isReady(bool checkMaster, int timeout) { + if (checkMaster && !_isMaster) { + log_e("Master mode is not active. Call begin(localName, true) to enable Master mode"); + return false; + } + if (!btStarted()) { + log_e("BT is not initialized. Call begin() first"); + return false; + } + TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS; + return (xEventGroupWaitBits(_spp_event_group, SPP_RUNNING, pdFALSE, pdTRUE, xTicksToWait) != 0); +} #endif diff --git a/libraries/BluetoothSerial/src/BluetoothSerial.h b/libraries/BluetoothSerial/src/BluetoothSerial.h old mode 100644 new mode 100755 index 3f4372e55d2..68269fa9ae6 --- a/libraries/BluetoothSerial/src/BluetoothSerial.h +++ b/libraries/BluetoothSerial/src/BluetoothSerial.h @@ -30,7 +30,7 @@ class BluetoothSerial: public Stream BluetoothSerial(void); ~BluetoothSerial(void); - bool begin(String localName=String()); + bool begin(String localName=String(), bool isMaster=false); int available(void); int peek(void); bool hasClient(void); @@ -41,6 +41,16 @@ class BluetoothSerial: public Stream void end(void); esp_err_t register_callback(esp_spp_cb_t * callback); + void enableSSP(); + bool setPin(const char *pin); + bool connect(String remoteName); + bool connect(uint8_t remoteAddress[]); + bool connect(); + bool connected(int timeout=0); + bool isReady(bool checkMaster=false, int timeout=0); + bool disconnect(); + bool unpairDevice(uint8_t remoteAddress[]); + private: String local_name; diff --git a/libraries/EEPROM/examples/eeprom_class/eeprom_class.ino b/libraries/EEPROM/examples/eeprom_class/eeprom_class.ino index 1e28dee8616..f5301f4ef1d 100644 --- a/libraries/EEPROM/examples/eeprom_class/eeprom_class.ino +++ b/libraries/EEPROM/examples/eeprom_class/eeprom_class.ino @@ -37,7 +37,8 @@ void setup() { ESP.restart(); } - char* name = "Teo Swee Ann"; + const char* name = "Teo Swee Ann"; + char rname[32]; double height = 5.8; uint32_t age = 47; @@ -60,10 +61,10 @@ void setup() { Serial.println("------------------------------------\n"); // Read: Variables <--- EEPROM stores - NAMES.get(0, name); + NAMES.get(0, rname); HEIGHT.get(0, height); AGE.get(0, age); - Serial.print("name: "); Serial.println(name); + Serial.print("name: "); Serial.println(rname); Serial.print("height: "); Serial.println(height); Serial.print("age: "); Serial.println(age); diff --git a/libraries/EEPROM/examples/eeprom_extra/eeprom_extra.ino b/libraries/EEPROM/examples/eeprom_extra/eeprom_extra.ino index 0ae4189a170..5ae01fb2268 100644 --- a/libraries/EEPROM/examples/eeprom_extra/eeprom_extra.ino +++ b/libraries/EEPROM/examples/eeprom_extra/eeprom_extra.ino @@ -49,11 +49,11 @@ void setup() { EEPROM.writeULong(address, 4294967295); // Same as writeUInt and readUInt address += sizeof(unsigned long); - int64_t value = -9223372036854775808; // -2^63 + int64_t value = -1223372036854775808LL; // -2^63 EEPROM.writeLong64(address, value); address += sizeof(int64_t); - uint64_t Value = 18446744073709551615; // 2^64 - 1 + uint64_t Value = 18446744073709551615ULL; // 2^64 - 1 EEPROM.writeULong64(address, Value); address += sizeof(uint64_t); diff --git a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino index 52f252f17b8..76f48b757a4 100644 --- a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino +++ b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino @@ -40,8 +40,6 @@ Method to print the touchpad by which ESP32 has been awaken from sleep */ void print_wakeup_touchpad(){ - touch_pad_t pin; - touchPin = esp_sleep_get_touchpad_wakeup_status(); switch(touchPin) diff --git a/libraries/ESP32/examples/ESPNow/Basic/Master/Master.ino b/libraries/ESP32/examples/ESPNow/Basic/Master/Master.ino index 9e3c02e287b..1cb9fb98845 100644 --- a/libraries/ESP32/examples/ESPNow/Basic/Master/Master.ino +++ b/libraries/ESP32/examples/ESPNow/Basic/Master/Master.ino @@ -88,7 +88,7 @@ void ScanForSlave() { Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println(""); // Get BSSID => Mac Address of the Slave int mac[6]; - if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) { + if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) { for (int ii = 0; ii < 6; ++ii ) { slave.peer_addr[ii] = (uint8_t) mac[ii]; } @@ -124,17 +124,15 @@ bool manageSlave() { } Serial.print("Slave Status: "); - const esp_now_peer_info_t *peer = &slave; - const uint8_t *peer_addr = slave.peer_addr; // check if the peer exists - bool exists = esp_now_is_peer_exist(peer_addr); + bool exists = esp_now_is_peer_exist(slave.peer_addr); if ( exists) { // Slave already paired. Serial.println("Already Paired"); return true; } else { // Slave not paired, attempt pair - esp_err_t addStatus = esp_now_add_peer(peer); + esp_err_t addStatus = esp_now_add_peer(&slave); if (addStatus == ESP_OK) { // Pair success Serial.println("Pair success"); @@ -168,9 +166,7 @@ bool manageSlave() { } void deletePeer() { - const esp_now_peer_info_t *peer = &slave; - const uint8_t *peer_addr = slave.peer_addr; - esp_err_t delStatus = esp_now_del_peer(peer_addr); + esp_err_t delStatus = esp_now_del_peer(slave.peer_addr); Serial.print("Slave Delete Status: "); if (delStatus == ESP_OK) { // Delete success diff --git a/libraries/ESP32/examples/ESPNow/Multi-Slave/Master/Master.ino b/libraries/ESP32/examples/ESPNow/Multi-Slave/Master/Master.ino index bbd783e6459..6e212dd1121 100644 --- a/libraries/ESP32/examples/ESPNow/Multi-Slave/Master/Master.ino +++ b/libraries/ESP32/examples/ESPNow/Multi-Slave/Master/Master.ino @@ -100,7 +100,7 @@ void ScanForSlave() { // Get BSSID => Mac Address of the Slave int mac[6]; - if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) { + if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) { for (int ii = 0; ii < 6; ++ii ) { slaves[SlaveCnt].peer_addr[ii] = (uint8_t) mac[ii]; } @@ -127,8 +127,6 @@ void ScanForSlave() { void manageSlave() { if (SlaveCnt > 0) { for (int i = 0; i < SlaveCnt; i++) { - const esp_now_peer_info_t *peer = &slaves[i]; - const uint8_t *peer_addr = slaves[i].peer_addr; Serial.print("Processing: "); for (int ii = 0; ii < 6; ++ii ) { Serial.print((uint8_t) slaves[i].peer_addr[ii], HEX); @@ -136,13 +134,13 @@ void manageSlave() { } Serial.print(" Status: "); // check if the peer exists - bool exists = esp_now_is_peer_exist(peer_addr); + bool exists = esp_now_is_peer_exist(slaves[i].peer_addr); if (exists) { // Slave already paired. Serial.println("Already Paired"); } else { // Slave not paired, attempt pair - esp_err_t addStatus = esp_now_add_peer(peer); + esp_err_t addStatus = esp_now_add_peer(&slaves[i]); if (addStatus == ESP_OK) { // Pair success Serial.println("Pair success"); diff --git a/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino b/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino index bdffff47067..54f2d2c983c 100644 --- a/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino +++ b/libraries/ESP32/examples/RMT/RMTLoopback/RMTLoopback.ino @@ -52,7 +52,7 @@ void loop() // Printout the received data plus the original values for (i=0; i<60; i++) { - Serial.printf("%08x=%08x ", my_data[i], data[i] ); + Serial.printf("%08x=%08x ", my_data[i].val, data[i].val ); if (!((i+1)%4)) Serial.println("\n"); } Serial.println("\n"); diff --git a/libraries/ESP32/examples/RMT/RMTReadXJT/RMTReadXJT.ino b/libraries/ESP32/examples/RMT/RMTReadXJT/RMTReadXJT.ino index e2e059fdfc9..29ab824d79d 100644 --- a/libraries/ESP32/examples/RMT/RMTReadXJT/RMTReadXJT.ino +++ b/libraries/ESP32/examples/RMT/RMTReadXJT/RMTReadXJT.ino @@ -141,7 +141,6 @@ static bool xjtReceiveBit(size_t index, bool bit){ } void parseRmt(rmt_data_t* items, size_t len, uint32_t* channels){ - size_t chan = 0; bool valid = true; rmt_data_t* it = NULL; diff --git a/libraries/FFat/examples/FFat_Test/FFat_Test.ino b/libraries/FFat/examples/FFat_Test/FFat_Test.ino index 2dc6e6ff2ee..f36d922557e 100644 --- a/libraries/FFat/examples/FFat_Test/FFat_Test.ino +++ b/libraries/FFat/examples/FFat_Test/FFat_Test.ino @@ -65,7 +65,7 @@ void writeFile(fs::FS &fs, const char * path, const char * message){ if(file.print(message)){ Serial.println("- file written"); } else { - Serial.println("- frite failed"); + Serial.println("- write failed"); } } @@ -165,8 +165,8 @@ void setup(){ return; } - Serial.printf("Total space: %10lu\n", FFat.totalBytes()); - Serial.printf("Free space: %10lu\n", FFat.freeBytes()); + Serial.printf("Total space: %10u\n", FFat.totalBytes()); + Serial.printf("Free space: %10u\n", FFat.freeBytes()); listDir(FFat, "/", 0); writeFile(FFat, "/hello.txt", "Hello "); appendFile(FFat, "/hello.txt", "World!\r\n"); @@ -175,7 +175,7 @@ void setup(){ readFile(FFat, "/foo.txt"); deleteFile(FFat, "/foo.txt"); testFileIO(FFat, "/test.txt"); - Serial.printf("Free space: %10lu\n", FFat.freeBytes()); + Serial.printf("Free space: %10u\n", FFat.freeBytes()); deleteFile(FFat, "/test.txt"); Serial.println( "Test complete" ); } diff --git a/libraries/FFat/src/FFat.cpp b/libraries/FFat/src/FFat.cpp index 2c53f3a338a..0d2b2cb26ab 100644 --- a/libraries/FFat/src/FFat.cpp +++ b/libraries/FFat/src/FFat.cpp @@ -40,20 +40,26 @@ const esp_partition_t *check_ffat_partition(const char* label) bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles, const char * partitionLabel) { - if(_wl_handle){ + if(_wl_handle != WL_INVALID_HANDLE){ log_w("Already Mounted!"); return true; } - if (!check_ffat_partition(partitionLabel)) return false; + if (!check_ffat_partition(partitionLabel)){ + log_e("No fat partition found on flash"); + return false; + } esp_vfs_fat_mount_config_t conf = { .format_if_mount_failed = formatOnFail, - .max_files = maxOpenFiles + .max_files = maxOpenFiles, + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE }; esp_err_t err = esp_vfs_fat_spiflash_mount(basePath, partitionLabel, &conf, &_wl_handle); if(err){ log_e("Mounting FFat partition failed! Error: %d", err); + esp_vfs_fat_spiflash_unmount(basePath, _wl_handle); + _wl_handle = WL_INVALID_HANDLE; return false; } _impl->mountpoint(basePath); @@ -62,13 +68,13 @@ bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles void F_Fat::end() { - if(_wl_handle){ + if(_wl_handle != WL_INVALID_HANDLE){ esp_err_t err = esp_vfs_fat_spiflash_unmount(_impl->mountpoint(), _wl_handle); if(err){ log_e("Unmounting FFat partition failed! Error: %d", err); return; } - _wl_handle = 0; + _wl_handle = WL_INVALID_HANDLE; _impl->mountpoint(NULL); } } @@ -77,7 +83,7 @@ bool F_Fat::format(bool full_wipe, char* partitionLabel) { esp_err_t result; bool res = true; - if(_wl_handle){ + if(_wl_handle != WL_INVALID_HANDLE){ log_w("Already Mounted!"); return false; } @@ -102,7 +108,8 @@ bool F_Fat::format(bool full_wipe, char* partitionLabel) // Now do a mount with format_if_fail (which it will) esp_vfs_fat_mount_config_t conf = { .format_if_mount_failed = true, - .max_files = 1 + .max_files = 1, + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE }; result = esp_vfs_fat_spiflash_mount("/format_ffat", partitionLabel, &conf, &temp_handle); esp_vfs_fat_spiflash_unmount("/format_ffat", temp_handle); diff --git a/libraries/FFat/src/FFat.h b/libraries/FFat/src/FFat.h index 7a5499efacb..a32c950bb6e 100644 --- a/libraries/FFat/src/FFat.h +++ b/libraries/FFat/src/FFat.h @@ -37,7 +37,7 @@ class F_Fat : public FS bool exists(const String& path); private: - wl_handle_t _wl_handle; + wl_handle_t _wl_handle = WL_INVALID_HANDLE; }; } diff --git a/libraries/SPIFFS/examples/SPIFFS_Test/SPIFFS_Test.ino b/libraries/SPIFFS/examples/SPIFFS_Test/SPIFFS_Test.ino index cfc111dc22a..730e90ebf50 100644 --- a/libraries/SPIFFS/examples/SPIFFS_Test/SPIFFS_Test.ino +++ b/libraries/SPIFFS/examples/SPIFFS_Test/SPIFFS_Test.ino @@ -63,7 +63,7 @@ void writeFile(fs::FS &fs, const char * path, const char * message){ if(file.print(message)){ Serial.println("- file written"); } else { - Serial.println("- frite failed"); + Serial.println("- write failed"); } } diff --git a/libraries/WebServer/src/WebServer.cpp b/libraries/WebServer/src/WebServer.cpp index 90416f90b1a..a510f109235 100644 --- a/libraries/WebServer/src/WebServer.cpp +++ b/libraries/WebServer/src/WebServer.cpp @@ -33,7 +33,7 @@ static const char AUTHORIZATION_HEADER[] = "Authorization"; -static const char qop_auth[] = "qop=auth"; +static const char qop_auth[] = "qop=\"auth\""; static const char WWW_Authenticate[] = "WWW-Authenticate"; static const char Content_Length[] = "Content-Length"; @@ -161,17 +161,17 @@ bool WebServer::authenticate(const char * username, const char * password){ } else if(authReq.startsWith(F("Digest"))) { authReq = authReq.substring(7); log_v("%s", authReq.c_str()); - String _username = _extractParam(authReq,F("username=\"")); + String _username = _extractParam(authReq,F("username=\""),'\"'); if(!_username.length() || _username != String(username)) { authReq = ""; return false; } // extracting required parameters for RFC 2069 simpler Digest - String _realm = _extractParam(authReq, F("realm=\"")); - String _nonce = _extractParam(authReq, F("nonce=\"")); - String _uri = _extractParam(authReq, F("uri=\"")); - String _response = _extractParam(authReq, F("response=\"")); - String _opaque = _extractParam(authReq, F("opaque=\"")); + String _realm = _extractParam(authReq, F("realm=\""),'\"'); + String _nonce = _extractParam(authReq, F("nonce=\""),'\"'); + String _uri = _extractParam(authReq, F("uri=\""),'\"'); + String _response = _extractParam(authReq, F("response=\""),'\"'); + String _opaque = _extractParam(authReq, F("opaque=\""),'\"'); if((!_realm.length()) || (!_nonce.length()) || (!_uri.length()) || (!_response.length()) || (!_opaque.length())) { authReq = ""; @@ -185,7 +185,7 @@ bool WebServer::authenticate(const char * username, const char * password){ String _nc,_cnonce; if(authReq.indexOf(FPSTR(qop_auth)) != -1) { _nc = _extractParam(authReq, F("nc="), ','); - _cnonce = _extractParam(authReq, F("cnonce=\"")); + _cnonce = _extractParam(authReq, F("cnonce=\""),'\"'); } String _H1 = md5str(String(username) + ':' + _realm + ':' + String(password)); log_v("Hash of user:realm:pass=%s", _H1.c_str()); diff --git a/libraries/WiFi/examples/ETH_LAN8720_internal_clock/ETH_LAN8720_internal_clock.ino b/libraries/WiFi/examples/ETH_LAN8720_internal_clock/ETH_LAN8720_internal_clock.ino index 482ee8142f8..6e726b7080e 100644 --- a/libraries/WiFi/examples/ETH_LAN8720_internal_clock/ETH_LAN8720_internal_clock.ino +++ b/libraries/WiFi/examples/ETH_LAN8720_internal_clock/ETH_LAN8720_internal_clock.ino @@ -10,6 +10,9 @@ * ETH_CLOCK_GPIO16_OUT - 50MHz clock from internal APLL output on GPIO16 - possibly an inverter is needed for LAN8720 * ETH_CLOCK_GPIO17_OUT - 50MHz clock from internal APLL inverted output on GPIO17 - tested with LAN8720 */ +#ifdef ETH_CLK_MODE +#undef ETH_CLK_MODE +#endif #define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT // Pin# of the enable signal for the external crystal oscillator (-1 to disable for internal APLL source) diff --git a/libraries/WiFi/examples/WiFiClientBasic/WiFiClientBasic.ino b/libraries/WiFi/examples/WiFiClientBasic/WiFiClientBasic.ino index 647e846f68a..ecfed5e1957 100644 --- a/libraries/WiFi/examples/WiFiClientBasic/WiFiClientBasic.ino +++ b/libraries/WiFi/examples/WiFiClientBasic/WiFiClientBasic.ino @@ -36,8 +36,10 @@ void setup() void loop() { - const uint16_t port = 80; - const char * host = "192.168.1.1"; // ip or dns +// const uint16_t port = 80; +// const char * host = "192.168.1.1"; // ip or dns + const uint16_t port = 1337; + const char * host = "192.168.1.10"; // ip or dns Serial.print("Connecting to "); Serial.println(host); @@ -53,11 +55,29 @@ void loop() } // This will send a request to the server - client.print("Send this data to the server"); - + //uncomment this line to send an arbitrary string to the server + //client.print("Send this data to the server"); + //uncomment this line to send a basic document request to the server + client.print("GET /index.html HTTP/1.1\n\n"); + + int maxloops = 0; + + //wait for the server's reply to become available + while (!client.available() && maxloops < 1000) + { + maxloops++; + delay(1); //delay 1 msec + } + if (client.available() > 0) + { //read back one line from the server String line = client.readStringUntil('\r'); - client.println(line); + Serial.println(line); + } + else + { + Serial.println("client.available() timed out "); + } Serial.println("Closing connection."); client.stop(); @@ -65,4 +85,3 @@ void loop() Serial.println("Waiting 5 seconds before restarting..."); delay(5000); } - diff --git a/libraries/WiFi/examples/WiFiClientEvents/WiFiClientEvents.ino b/libraries/WiFi/examples/WiFiClientEvents/WiFiClientEvents.ino index 61b9776d30a..a7b029481e5 100644 --- a/libraries/WiFi/examples/WiFiClientEvents/WiFiClientEvents.ino +++ b/libraries/WiFi/examples/WiFiClientEvents/WiFiClientEvents.ino @@ -121,6 +121,7 @@ void WiFiEvent(WiFiEvent_t event) case SYSTEM_EVENT_ETH_GOT_IP: Serial.println("Obtained IP address"); break; + default: break; }} void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) diff --git a/libraries/WiFi/examples/WiFiUDPClient/WiFiUDPClient.ino b/libraries/WiFi/examples/WiFiUDPClient/WiFiUDPClient.ino index 04d4effd0a8..310989f0c1f 100644 --- a/libraries/WiFi/examples/WiFiUDPClient/WiFiUDPClient.ino +++ b/libraries/WiFi/examples/WiFiUDPClient/WiFiUDPClient.ino @@ -34,7 +34,7 @@ void loop(){ if(connected){ //Send a packet udp.beginPacket(udpAddress,udpPort); - udp.printf("Seconds since boot: %u", millis()/1000); + udp.printf("Seconds since boot: %lu", millis()/1000); udp.endPacket(); } //Wait for 1 second @@ -71,5 +71,6 @@ void WiFiEvent(WiFiEvent_t event){ Serial.println("WiFi lost connection"); connected = false; break; + default: break; } } diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index c972fe6708b..9a6169357f4 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -47,7 +47,6 @@ extern "C" { #include "esp32-hal-log.h" #include - #include "sdkconfig.h" static xQueueHandle _network_event_queue; @@ -133,24 +132,19 @@ static bool wifiLowLevelDeinit(){ static bool _esp_wifi_started = false; -static bool espWiFiStart(bool persistent){ +static bool espWiFiStart(){ if(_esp_wifi_started){ return true; } - if(!wifiLowLevelInit(persistent)){ - return false; - } esp_err_t err = esp_wifi_start(); if (err != ESP_OK) { log_e("esp_wifi_start %d", err); - wifiLowLevelDeinit(); return false; } _esp_wifi_started = true; system_event_t event; event.event_id = SYSTEM_EVENT_WIFI_READY; WiFiGenericClass::_eventCallback(nullptr, &event); - return true; } @@ -190,6 +184,7 @@ wifi_event_id_t WiFiEventCbList::current_id = 1; static std::vector cbEventList; bool WiFiGenericClass::_persistent = true; +bool WiFiGenericClass::_long_range = false; wifi_mode_t WiFiGenericClass::_forceSleepLastMode = WIFI_MODE_NULL; WiFiGenericClass::WiFiGenericClass() @@ -471,6 +466,16 @@ void WiFiGenericClass::persistent(bool persistent) } +/** + * enable WiFi long range mode + * @param enable + */ +void WiFiGenericClass::enableLongRange(bool enable) +{ + _long_range = enable; +} + + /** * set new mode * @param m WiFiMode_t @@ -482,7 +487,7 @@ bool WiFiGenericClass::mode(wifi_mode_t m) return true; } if(!cm && m){ - if(!espWiFiStart(_persistent)){ + if(!wifiLowLevelInit(_persistent)){ return false; } } else if(cm && !m){ @@ -495,6 +500,25 @@ bool WiFiGenericClass::mode(wifi_mode_t m) log_e("Could not set mode! %d", err); return false; } + if(_long_range){ + if(m & WIFI_MODE_STA){ + err = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); + if(err != ESP_OK){ + log_e("Could not enable long range on STA! %d", err); + return false; + } + } + if(m & WIFI_MODE_AP){ + err = esp_wifi_set_protocol(WIFI_IF_AP, WIFI_PROTOCOL_LR); + if(err != ESP_OK){ + log_e("Could not enable long range on AP! %d", err); + return false; + } + } + } + if(!espWiFiStart()){ + return false; + } return true; } @@ -504,7 +528,7 @@ bool WiFiGenericClass::mode(wifi_mode_t m) */ wifi_mode_t WiFiGenericClass::getMode() { - if(!_esp_wifi_started){ + if(!lowLevelInitDone){ return WIFI_MODE_NULL; } wifi_mode_t mode; diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index ad0cd260767..65f5d23b464 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -83,6 +83,7 @@ class WiFiGenericClass int32_t channel(void); void persistent(bool persistent); + void enableLongRange(bool enable); static bool mode(wifi_mode_t); static wifi_mode_t getMode(); @@ -100,6 +101,7 @@ class WiFiGenericClass protected: static bool _persistent; + static bool _long_range; static wifi_mode_t _forceSleepLastMode; static int setStatusBits(int bits); diff --git a/libraries/WiFi/src/WiFiScan.h b/libraries/WiFi/src/WiFiScan.h index 41ab00802e3..3ddcbeac692 100644 --- a/libraries/WiFi/src/WiFiScan.h +++ b/libraries/WiFi/src/WiFiScan.h @@ -45,6 +45,7 @@ class WiFiScanClass uint8_t * BSSID(uint8_t networkItem); String BSSIDstr(uint8_t networkItem); int32_t channel(uint8_t networkItem); + static void * getScanInfoByIndex(int i) { return _getScanInfoByIndex(i); }; static void _scanDone(); protected: diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 9baa377f8ad..2e6533eda9d 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -83,6 +83,13 @@ "archiveFileName": "xtensa-esp32-elf-linux32-1.22.0-80-g6c4433a-5.2.0.tar.gz", "checksum": "SHA-256:b4055695ffc2dfc0bcb6dafdc2572a6e01151c4179ef5fa972b3fcb2183eb155", "size": "45566336" + }, + { + "host": "arm-linux-gnueabihf", + "url": "https://dl.espressif.com/dl/xtensa-esp32-elf-linux-armel-1.22.0-87-gb57bad3-5.2.0.tar.gz", + "archiveFileName": "xtensa-esp32-elf-linux-armel-1.22.0-87-gb57bad3-5.2.0.tar.gz", + "checksum": "SHA-256:9c68c87bb23b1256dc0a1859b515946763e5292dcab4a4159a52fae5618ce861", + "size": "50655584" } ] }, diff --git a/platform.txt b/platform.txt index 23d0e326cbf..aad26366171 100644 --- a/platform.txt +++ b/platform.txt @@ -22,20 +22,20 @@ compiler.warning_flags.all=-Wall -Werror=all -Wextra compiler.path={runtime.tools.xtensa-esp32-elf-gcc.path}/bin/ compiler.sdk.path={runtime.platform.path}/tools/sdk -compiler.cpreprocessor.flags=-DESP_PLATFORM -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DHAVE_CONFIG_H "-I{compiler.sdk.path}/include/config" "-I{compiler.sdk.path}/include/app_trace" "-I{compiler.sdk.path}/include/app_update" "-I{compiler.sdk.path}/include/asio" "-I{compiler.sdk.path}/include/bootloader_support" "-I{compiler.sdk.path}/include/bt" "-I{compiler.sdk.path}/include/coap" "-I{compiler.sdk.path}/include/console" "-I{compiler.sdk.path}/include/driver" "-I{compiler.sdk.path}/include/esp-tls" "-I{compiler.sdk.path}/include/esp32" "-I{compiler.sdk.path}/include/esp_adc_cal" "-I{compiler.sdk.path}/include/esp_event" "-I{compiler.sdk.path}/include/esp_http_client" "-I{compiler.sdk.path}/include/esp_http_server" "-I{compiler.sdk.path}/include/esp_https_ota" "-I{compiler.sdk.path}/include/esp_ringbuf" "-I{compiler.sdk.path}/include/ethernet" "-I{compiler.sdk.path}/include/expat" "-I{compiler.sdk.path}/include/fatfs" "-I{compiler.sdk.path}/include/freemodbus" "-I{compiler.sdk.path}/include/freertos" "-I{compiler.sdk.path}/include/heap" "-I{compiler.sdk.path}/include/idf_test" "-I{compiler.sdk.path}/include/jsmn" "-I{compiler.sdk.path}/include/json" "-I{compiler.sdk.path}/include/libsodium" "-I{compiler.sdk.path}/include/log" "-I{compiler.sdk.path}/include/lwip" "-I{compiler.sdk.path}/include/mbedtls" "-I{compiler.sdk.path}/include/mdns" "-I{compiler.sdk.path}/include/micro-ecc" "-I{compiler.sdk.path}/include/mqtt" "-I{compiler.sdk.path}/include/newlib" "-I{compiler.sdk.path}/include/nghttp" "-I{compiler.sdk.path}/include/nvs_flash" "-I{compiler.sdk.path}/include/openssl" "-I{compiler.sdk.path}/include/protobuf-c" "-I{compiler.sdk.path}/include/protocomm" "-I{compiler.sdk.path}/include/pthread" "-I{compiler.sdk.path}/include/sdmmc" "-I{compiler.sdk.path}/include/smartconfig_ack" "-I{compiler.sdk.path}/include/soc" "-I{compiler.sdk.path}/include/spi_flash" "-I{compiler.sdk.path}/include/spiffs" "-I{compiler.sdk.path}/include/tcp_transport" "-I{compiler.sdk.path}/include/tcpip_adapter" "-I{compiler.sdk.path}/include/ulp" "-I{compiler.sdk.path}/include/vfs" "-I{compiler.sdk.path}/include/wear_levelling" "-I{compiler.sdk.path}/include/wifi_provisioning" "-I{compiler.sdk.path}/include/wpa_supplicant" "-I{compiler.sdk.path}/include/xtensa-debug-module" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/esp32-camera" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/fb_gfx" +compiler.cpreprocessor.flags=-DESP_PLATFORM -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DHAVE_CONFIG_H -DGCC_NOT_5_2_0=0 -DWITH_POSIX "-I{compiler.sdk.path}/include/config" "-I{compiler.sdk.path}/include/app_trace" "-I{compiler.sdk.path}/include/app_update" "-I{compiler.sdk.path}/include/asio" "-I{compiler.sdk.path}/include/bootloader_support" "-I{compiler.sdk.path}/include/bt" "-I{compiler.sdk.path}/include/coap" "-I{compiler.sdk.path}/include/console" "-I{compiler.sdk.path}/include/driver" "-I{compiler.sdk.path}/include/esp-tls" "-I{compiler.sdk.path}/include/esp32" "-I{compiler.sdk.path}/include/esp_adc_cal" "-I{compiler.sdk.path}/include/esp_event" "-I{compiler.sdk.path}/include/esp_http_client" "-I{compiler.sdk.path}/include/esp_http_server" "-I{compiler.sdk.path}/include/esp_https_ota" "-I{compiler.sdk.path}/include/esp_ringbuf" "-I{compiler.sdk.path}/include/ethernet" "-I{compiler.sdk.path}/include/expat" "-I{compiler.sdk.path}/include/fatfs" "-I{compiler.sdk.path}/include/freemodbus" "-I{compiler.sdk.path}/include/freertos" "-I{compiler.sdk.path}/include/heap" "-I{compiler.sdk.path}/include/idf_test" "-I{compiler.sdk.path}/include/jsmn" "-I{compiler.sdk.path}/include/json" "-I{compiler.sdk.path}/include/libsodium" "-I{compiler.sdk.path}/include/log" "-I{compiler.sdk.path}/include/lwip" "-I{compiler.sdk.path}/include/mbedtls" "-I{compiler.sdk.path}/include/mdns" "-I{compiler.sdk.path}/include/micro-ecc" "-I{compiler.sdk.path}/include/mqtt" "-I{compiler.sdk.path}/include/newlib" "-I{compiler.sdk.path}/include/nghttp" "-I{compiler.sdk.path}/include/nvs_flash" "-I{compiler.sdk.path}/include/openssl" "-I{compiler.sdk.path}/include/protobuf-c" "-I{compiler.sdk.path}/include/protocomm" "-I{compiler.sdk.path}/include/pthread" "-I{compiler.sdk.path}/include/sdmmc" "-I{compiler.sdk.path}/include/smartconfig_ack" "-I{compiler.sdk.path}/include/soc" "-I{compiler.sdk.path}/include/spi_flash" "-I{compiler.sdk.path}/include/spiffs" "-I{compiler.sdk.path}/include/tcp_transport" "-I{compiler.sdk.path}/include/tcpip_adapter" "-I{compiler.sdk.path}/include/ulp" "-I{compiler.sdk.path}/include/vfs" "-I{compiler.sdk.path}/include/wear_levelling" "-I{compiler.sdk.path}/include/wifi_provisioning" "-I{compiler.sdk.path}/include/wpa_supplicant" "-I{compiler.sdk.path}/include/xtensa-debug-module" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/esp32-camera" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/fb_gfx" compiler.c.cmd=xtensa-esp32-elf-gcc -compiler.c.flags=-std=gnu99 -Os -g3 -fstack-protector -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wpointer-arith {compiler.warning_flags} -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -Wno-old-style-declaration -MMD -c +compiler.c.flags=-std=gnu99 -Os -g3 -fstack-protector -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wpointer-arith {compiler.warning_flags} -Wno-maybe-uninitialized -Wno-unused-function -Wno-unused-but-set-variable -Wno-unused-variable -Wno-deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -Wno-old-style-declaration -MMD -c compiler.cpp.cmd=xtensa-esp32-elf-g++ -compiler.cpp.flags=-std=gnu++11 -fno-exceptions -Os -g3 -Wpointer-arith -fexceptions -fstack-protector -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib {compiler.warning_flags} -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -fno-rtti -MMD -c +compiler.cpp.flags=-std=gnu++11 -Os -g3 -Wpointer-arith -fexceptions -fstack-protector -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib {compiler.warning_flags} -Wno-error=maybe-uninitialized -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-unused-but-set-parameter -Wno-missing-field-initializers -Wno-sign-compare -fno-rtti -MMD -c compiler.S.cmd=xtensa-esp32-elf-gcc compiler.S.flags=-c -g3 -x assembler-with-cpp -MMD -mlongcalls compiler.c.elf.cmd=xtensa-esp32-elf-gcc compiler.c.elf.flags=-nostdlib "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" -T esp32_out.ld -T esp32.common.ld -T esp32.rom.ld -T esp32.peripherals.ld -T esp32.rom.libgcc.ld -T esp32.rom.spiram_incompatible_fns.ld -u ld_include_panic_highint_hdl -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--undefined=uxTopUsedPriority -u __cxa_guard_dummy -u __cxx_fatal_exception -compiler.c.elf.libs=-lgcc -lopenssl -lbtdm_app -lfatfs -lwps -lcoexist -lwear_levelling -lesp_http_client -lprotobuf-c -lhal -lnewlib -ldriver -lbootloader_support -lpp -lfreemodbus -lmesh -lsmartconfig -ljsmn -lwpa -lethernet -lphy -lapp_trace -lconsole -lulp -lwpa_supplicant -lfreertos -lbt -lmicro-ecc -lesp32-camera -lcxx -lxtensa-debug-module -ltcp_transport -lmdns -lvfs -lesp_ringbuf -lsoc -lcore -lfb_gfx -lsdmmc -llibsodium -lcoap -ltcpip_adapter -lprotocomm -lesp_event -limage_util -lc_nano -lesp-tls -lasio -lrtc -lspi_flash -lwpa2 -lwifi_provisioning -lesp32 -lface_recognition -lapp_update -lnghttp -lspiffs -lface_detection -lespnow -lnvs_flash -lesp_adc_cal -llog -ldl_lib -lsmartconfig_ack -lexpat -lm -lfr -lmqtt -lc -lheap -lmbedtls -llwip -lnet80211 -lesp_http_server -lpthread -ljson -lesp_https_ota -lfd -lstdc++ +compiler.c.elf.libs=-lgcc -lesp32 -lphy -lesp_http_client -lmbedtls -lrtc -lesp_http_server -lbtdm_app -lspiffs -lbootloader_support -lmdns -lnvs_flash -lfatfs -lpp -lnet80211 -ljsmn -lface_detection -llibsodium -lvfs -ldl_lib -llog -lfreertos -lcxx -lsmartconfig_ack -lxtensa-debug-module -lheap -ltcpip_adapter -lmqtt -lulp -lfd -lfb_gfx -lnghttp -lprotocomm -lsmartconfig -lm -lethernet -limage_util -lc_nano -lsoc -ltcp_transport -lc -lmicro-ecc -lface_recognition -ljson -lwpa_supplicant -lmesh -lesp_https_ota -lwpa2 -lexpat -llwip -lwear_levelling -lapp_update -ldriver -lbt -lespnow -lcoap -lasio -lnewlib -lconsole -lapp_trace -lesp32-camera -lhal -lprotobuf-c -lsdmmc -lcore -lpthread -lcoexist -lfreemodbus -lspi_flash -lesp-tls -lwpa -lwifi_provisioning -lwps -lesp_adc_cal -lesp_event -lopenssl -lesp_ringbuf -lfr -lstdc++ compiler.as.cmd=xtensa-esp32-elf-as @@ -61,6 +61,13 @@ compiler.ar.extra_flags= compiler.objcopy.eep.extra_flags= compiler.elf2hex.extra_flags= +# Build Dir: {build.path} +# Sketch Dir: {build.source.path} +recipe.hooks.prebuild.1.pattern=bash -c "[ ! -f {build.source.path}/partitions.csv ] || cp -f {build.source.path}/partitions.csv {build.path}/partitions.csv" +recipe.hooks.prebuild.2.pattern=bash -c "[ -f {build.path}/partitions.csv ] || cp {runtime.platform.path}/tools/partitions/{build.partitions}.csv {build.path}/partitions.csv" +recipe.hooks.prebuild.1.pattern.windows=cmd /c if exist "{build.source.path}\partitions.csv" copy /y "{build.source.path}\partitions.csv" "{build.path}\partitions.csv" +recipe.hooks.prebuild.2.pattern.windows=cmd /c if not exist "{build.path}\partitions.csv" copy "{runtime.platform.path}\tools\partitions\{build.partitions}.csv" "{build.path}\partitions.csv" + ## Compile c files recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" @@ -77,7 +84,7 @@ recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compil recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group -Wl,-EL -o "{build.path}/{build.project_name}.elf" ## Create eeprom -recipe.objcopy.eep.pattern={tools.gen_esp32part.cmd} -q "{runtime.platform.path}/tools/partitions/{build.partitions}.csv" "{build.path}/{build.project_name}.partitions.bin" +recipe.objcopy.eep.pattern={tools.gen_esp32part.cmd} -q "{build.path}/partitions.csv" "{build.path}/{build.project_name}.partitions.bin" ## Create hex recipe.objcopy.hex.pattern="{tools.esptool_py.path}/{tools.esptool_py.cmd}" --chip esp32 elf2image --flash_mode "{build.flash_mode}" --flash_freq "{build.flash_freq}" --flash_size "{build.flash_size}" -o "{build.path}/{build.project_name}.bin" "{build.path}/{build.project_name}.elf" diff --git a/tools/ci/build-release.sh b/tools/ci/build-release.sh deleted file mode 100755 index 6d95fba13ae..00000000000 --- a/tools/ci/build-release.sh +++ /dev/null @@ -1,379 +0,0 @@ -#!/bin/bash - -if [ -z "$TRAVIS_TAG" ]; then - echo "Skipping Packaging: Regular build" - exit 0 -fi - -############################################################ -# $1 - download link -# $2 - JSON output file -function downloadAndMergePackageJSON() -{ - echo - echo " ---Package JSON definition merge BEGIN--->" - - jsonLink=$1 - jsonOut=$2 - curlAuthToken=$3 - outDirectory=$4 - - echo " - remote package JSON: $jsonLink (source)" - echo " - current package JSON: $jsonOut (target)" - - old_json=$outDirectory/oldJson.json - merged_json=$outDirectory/mergedJson.json - - #DEBUG - #echo " Local tmp for remote JSON: $old_json" - #echo " Merge output JSON: $merged_json" - - echo " - downloading JSON package definition: $jsonLink ..." - - # Authentication through HTTP headers might fail on redirection due to bug in cURL (https://curl.haxx.se/docs/adv_2018-b3bf.html - headers are resent to the target location including the original authentication) - # Notes: - # - eg AmazonAWS fails with Bad Request due to having maximum 1 authentication mechanism per a request, might be general issue - # - it's a first-class credential leakage - # - the fix is available in cURL 7.58.0+, however, TravisCI is not yet updated (May 29, 2018) - see https://docs.travis-ci.com/user/build-environment-updates - # - TravisCI workaround: updating build environment through .travis.yml (ie install required version of cURL using apt-get, see https://docs.travis-ci.com/user/installing-dependencies/) - # - previous point not used on purpose (build time increase, possible failure corrupts whole build, etc) but it's good to know there's a way out of hell - # - local workaround: authentication through 'access_token' as GET parameter works smoothly, however, HTTP headers are preferred - - #curl --verbose -sH "Authorization: token $curlAuthToken" -L -o "$old_json" "$jsonLink" - curl -L -o "$old_json" "$jsonLink?access_token=$curlAuthToken" - if [ $? -ne 0 ]; then echo "FAILED: $? => aborting"; exit 1; fi - - - #curl -L -o "$old_json" "$jsonLink" - - echo " - merging $old_json into $jsonOut ..." - - echo - set +e - stdbuf -oL python package/merge_packages.py "$jsonOut" "$old_json" > "$merged_json" - set -e #supposed to be ON by default - echo - - set -v - if [ ! -s $merged_json ]; then - rm -f "$merged_json" - echo " Done: nothing to merge ($merged_json empty) => $jsonOut remains unchanged" - else - rm -f "$jsonOut" - mv "$merged_json" "$jsonOut" - echo " Done: JSON data successfully merged to $jsonOut" - fi - - rm -f "$old_json" - set +v - echo " <---Package JSON definition merge END---" - echo -} -############################################################ - -#Cmdline options -# -a: GitHub API access token -# -d: output directory to store the (pre)release filedir set - -set -e - -echo -echo "===================================================================" -echo "RELEASE PACKAGE PUBLISHING ARRANGEMENTS (GitHub/Arduino compliance)" -echo "===================================================================" -echo -cmdLine=`basename $0 $@` -echo "Cmdline: ${cmdLine}" - -# cURL authentication token -while getopts ":a:,:d:" opt; do - case $opt in - a) - curlAuth=$OPTARG - #echo " ACCESS TOKEN: $curlAuth" >&2 - ;; - d) - releaseDir=$OPTARG - #echo " RELEASE OUTPUT DIRECTORY: $releaseDir" >&2 - ;; - \?) - echo "Error: invalid option -$OPTARG => aborting" >&2 - exit 1 - ;; - :) - echo "Error: option -$OPTARG requires an argument => aborting" >&2 - exit 1 - ;; - esac -done - -# where we at? -echo -echo "Prequisite check:" -if [ -z "$TRAVIS_BUILD_DIR" ]; then - echo " - non-TravisCI environment" - cd "$( dirname ${BASH_SOURCE[0]} )"/.. - bTravisRun=0 -else - echo " - TravisCI run" - cd $TRAVIS_BUILD_DIR - bTravisRun=1 -fi - -# no tag, no love -if [ -z "$TRAVIS_TAG" ] && [ $bTravisRun -eq 1 ]; then - echo "Warning: non-tagged builds not supported in Travis CI environment => exiting" - exit 0 -fi - -echo -echo "Package build settings:" -echo "=======================" - -# source directory -srcdir=`pwd` -echo "Current working directory: ${srcdir}" - -# target directory for actual release fileset -if [ -z "$releaseDir" ]; then - releaseDir=release -fi -echo "Release output directory: $releaseDir" - -# Git versions, branch names, tags -branch_name="" -verx="" -extent="" - -if [ -z "$TRAVIS_TAG" ]; then - branch_name=`git rev-parse --abbrev-ref HEAD 2>/dev/null` - ver=`sed -n -E 's/version=([0-9.]+)/\1/p' platform.txt` -else - ver=$TRAVIS_TAG -fi -verx=`git rev-parse --short=8 HEAD 2>/dev/null` - -# Package name resolving (case-insensitive): -# - unknown branch, master branch or branch in detached state (HEAD revision) use only the tag's name as version string (esp32-$TAG_NAME, eg 'esp32-1.0.0-RC1') -# - all other branches use long-version string (esp32-$BRANCH_NAME-$GITREV_NUMBER_SHORT, eg 'esp32-idf_update-cde668da') - -shopt -s nocasematch - -if [ ! -z "$branch_name" ] && [ "$branch_name" != "master" ] && [ "$branch_name" != "head" ]; then - extent="-$branch_name-$verx" -fi - -package_name=esp32-$ver$extent - -shopt -u nocasematch - -echo "Package version: $ver" -echo "Git branch name: $branch_name" -echo "Git revision number: $verx" -echo "Package name extension: $extent" -echo "Travis CI tag: $TRAVIS_TAG" -echo "Release package name: $package_name" - -# Set REMOTE_URL environment variable to the address where the package will be -# available for download. This gets written into package json file. - -if [ -z "$REMOTE_URL" ]; then - REMOTE_URL="http://localhost:8000" - remoteEchoOut="${REMOTE_URL} (REMOTE_URL variable not defined, using default)" -else - remoteEchoOut="${REMOTE_URL}" -fi -echo "Target URL for download (JSON incl): ${remoteEchoOut}" - -# Create directory for the package -outdir=$releaseDir/$package_name -echo "Local temp directory: $outdir" - -rm -rf $releaseDir -mkdir -p $outdir - -# Copy files required for the package release: -echo -echo "Package build processing:" -echo "=========================" -echo -echo "Prepare files for the package main archive:" -echo " - copying neccessary files from current Git repository..." - -# -cp -f $srcdir/boards.txt $outdir/ -cp -f $srcdir/platform.txt $outdir/ -cp -f $srcdir/programmers.txt $outdir/ - -# -# cores/ -# libraries/ -# variants/ -# tools/partitions/ -cp -Rf $srcdir/cores $outdir/ -cp -Rf $srcdir/libraries $outdir/ -cp -Rf $srcdir/variants $outdir/ -mkdir -p $outdir/tools -cp -Rf $srcdir/tools/partitions $outdir/tools/ - -# -# tools/sdk/ -cp -Rf $srcdir/tools/sdk $outdir/tools/ - -# tools/ -cp -f $srcdir/tools/espota.exe $outdir/tools/ -cp -f $srcdir/tools/espota.py $outdir/tools/ -cp -f $srcdir/tools/esptool.py $outdir/tools/ -cp -f $srcdir/tools/gen_esp32part.py $outdir/tools/ -cp -f $srcdir/tools/gen_esp32part.exe $outdir/tools/ - -echo " - cleaning *.DS_Store files..." -find $outdir -name '*.DS_Store' -exec rm -f {} \; - -# Do some replacements in platform.txt file, which are required because IDE -# handles tool paths differently when package is installed in hardware folder -echo " - updating platform.txt..." -cat $srcdir/platform.txt | \ -sed "s/version=.*/version=$ver$extent/g" | \ -sed 's/runtime.tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}\/tools\/xtensa-esp32-elf//g' | \ -sed 's/tools.esptool_py.path={runtime.platform.path}\/tools\/esptool/tools.esptool_py.path=\{runtime.tools.esptool_py.path\}/g' \ - > $outdir/platform.txt - -# Put core version and short hash of git version into core_version.h -ver_define=`echo $ver | tr "[:lower:].\055" "[:upper:]_"` -echo " - generating C/C++ header defines ($ver_define -> /cores/esp32/core_version.h)..." - -echo \#define ARDUINO_ESP32_GIT_VER 0x$verx >$outdir/cores/esp32/core_version.h -echo \#define ARDUINO_ESP32_GIT_DESC `git describe --tags 2>/dev/null` >>$outdir/cores/esp32/core_version.h -echo \#define ARDUINO_ESP32_RELEASE_$ver_define >>$outdir/cores/esp32/core_version.h -echo \#define ARDUINO_ESP32_RELEASE \"$ver_define\" >>$outdir/cores/esp32/core_version.h - -# Store submodules' current versions -echo " - getting submodule list (${releaseDir}/submodules.txt)..." -git submodule status > $releaseDir/submodules.txt - -# remove all .git* files -echo " - removing *.git files possibly fetched to package tempdir..." -find $outdir -name '*.git*' -type f -delete - -# Zip the package -package_name_zip=$package_name.zip -echo " - creating package ZIP archive (${package_name_zip})..." - -pushd $releaseDir >/dev/null - -zip -qr $package_name_zip $package_name -if [ $? -ne 0 ]; then echo " !error: failed to create ${package_name_zip} (ZIP errno: $?) => aborting"; exit 1; fi - -# Calculate SHA sum and size of ZIP archive -sha=`shasum -a 256 $package_name_zip | cut -f 1 -d ' '` -size=`/bin/ls -l $package_name_zip | awk '{print $5}'` -echo " ${package_name_zip} creation OK (size: $size, sha2: $sha)" -echo - -echo "Making $package_name JSON definition file(s):" - -popd >/dev/null - -PACKAGE_JSON_DEV="package_esp32_dev_index.json" -PACKAGE_JSON_REL="package_esp32_index.json" - -# figure out the package type (release / pre-release) -shopt -s nocasematch -if [[ $TRAVIS_TAG == *-RC* ]]; then - bIsPrerelease=1 - package_name_json=$PACKAGE_JSON_DEV - echo " - package type: PRE-RELEASE, JSON def.file: $PACKAGE_JSON_DEV" -else - bIsPrerelease=0 - package_name_json=$PACKAGE_JSON_REL - echo " - package type: RELEASE, JSON def.files: $PACKAGE_JSON_REL, $PACKAGE_JSON_DEV" -fi -shopt -u nocasematch - -# Cleanup temporary work dir -rm -rf $outdir - -# Get all previously released versions -echo " - fetching previous (pre)release versions from GitHub..." - -set +e - -releasesJson=$releaseDir/releases.json -curl -sH "Authorization: token $curlAuth" https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases > $releasesJson -if [ $? -ne 0 ]; then echo "FAILED: $? => aborting"; exit 1; fi - -prev_release=$(jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name' ${releasesJson}) -prev_any_release=$(jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name' ${releasesJson}) -prev_pre_release=$(jq -e -r '. | map(select(.draft == false and .prerelease == true)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name' ${releasesJson}) - -shopt -s nocasematch -if [ "$prev_any_release" == "$TRAVIS_TAG" ]; then - prev_release=$(jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name' ${releasesJson}) - prev_any_release=$(jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name' ${releasesJson}) - prev_pre_release=$(jq -e -r '. | map(select(.draft == false and .prerelease == true)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name' ${releasesJson}) -fi -shopt -u nocasematch - -set -e - -rm -f "$releasesJson" - -echo " previous Release: $prev_release" -echo " previous Pre-release: $prev_pre_release" -echo " previous (any)release: $prev_any_release" - -# add generated items to JSON package-definition contents -jq_arg=".packages[0].platforms[0].version = \"$ver\" | \ - .packages[0].platforms[0].url = \"$REMOTE_URL/$package_name_zip\" |\ - .packages[0].platforms[0].archiveFileName = \"$package_name_zip\"" - -jq_arg="$jq_arg |\ - .packages[0].platforms[0].size = \"$size\" |\ - .packages[0].platforms[0].checksum = \"SHA-256:$sha\"" - -# always get DEV version of JSON (included in both RC/REL) -pkgJsonDev=$releaseDir/$PACKAGE_JSON_DEV -echo " - generating/merging _DEV_ JSON file (${pkgJsonDev})..." - -cat $srcdir/package/package_esp32_index.template.json | jq "$jq_arg" > $pkgJsonDev -cd $srcdir -if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then - downloadAndMergePackageJSON "https://github.com/$TRAVIS_REPO_SLUG/releases/download/${prev_any_release}/${PACKAGE_JSON_DEV}" "${pkgJsonDev}" "${curlAuth}" "$releaseDir" - - # Release notes: GIT log comments (prev_any_release, current_release> - echo " - executing: git log --oneline $prev_any_release.." - git log --oneline $prev_any_release.. > $releaseDir/commits.txt -fi - -# for RELEASE run update REL JSON as well -if [ $bIsPrerelease -eq 0 ]; then - - pkgJsonRel=$releaseDir/$PACKAGE_JSON_REL - echo " - generating/merging _REL_ JSON file (${pkgJsonRel})..." - - cat $srcdir/package/package_esp32_index.template.json | jq "$jq_arg" > $pkgJsonRel - if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then - downloadAndMergePackageJSON "https://github.com/$TRAVIS_REPO_SLUG/releases/download/${prev_release}/${PACKAGE_JSON_REL}" "${pkgJsonRel}" "${curlAuth}" "$releaseDir" - - # Release notes: GIT log comments (prev_release, current_release> - echo " - executing: git log --oneline $prev_release.." - git log --oneline $prev_release.. > $releaseDir/commits.txt - fi -fi - -echo -echo "JSON definition file(s) creation OK" - -echo -echo "===================================================================" -echo "Package preparation done ('$releaseDir' contents):" -fileset=`ls -1 $releaseDir` -echo -e $fileset - -echo -echo "===================================================================" -echo "===================================================================" -echo "'$package_name' ready for publishing, processing completed." -echo "===================================================================" -echo diff --git a/tools/ci/build-tests.sh b/tools/ci/build-tests.sh deleted file mode 100755 index 6ec5e2feac8..00000000000 --- a/tools/ci/build-tests.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash - -if [ ! -z "$TRAVIS_TAG" ]; then - echo "Skipping Test: Tagged build" - exit 0 -fi - -CHUNK_INDEX=$1 -CHUNKS_CNT=$2 -BUILD_PIO=0 -if [ "$#" -lt 2 ]; then - echo "Building all sketches" - CHUNK_INDEX=0 - CHUNKS_CNT=1 - BUILD_PIO=1 -fi -if [ "$CHUNKS_CNT" -le 0 ]; then - CHUNK_INDEX=0 - CHUNKS_CNT=1 - BUILD_PIO=1 -fi -if [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ]; then - CHUNK_INDEX=$CHUNKS_CNT -fi -if [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then - BUILD_PIO=1 -fi - -# CMake Test -if [ "$CHUNK_INDEX" -eq 0 ]; then - echo -e "travis_fold:start:check_cmakelists" - tools/ci/check-cmakelists.sh - if [ $? -ne 0 ]; then exit 1; fi - echo -e "travis_fold:end:check_cmakelists" -fi - -if [ "$BUILD_PIO" -eq 0 ]; then - # ArduinoIDE Test - echo -e "travis_fold:start:prep_arduino_ide" - tools/ci/prep-arduino-ide.sh - if [ $? -ne 0 ]; then exit 1; fi - echo -e "travis_fold:end:prep_arduino_ide" - - echo -e "travis_fold:start:test_arduino_ide" - tools/ci/test-arduino-ide.sh $CHUNK_INDEX $CHUNKS_CNT - if [ $? -ne 0 ]; then exit 1; fi - echo -e "travis_fold:end:test_arduino_ide" - - echo -e "travis_fold:start:size_report" - cat size.log - echo -e "travis_fold:end:size_report" -else - # PlatformIO Test - echo -e "travis_fold:start:prep_platformio" - cd tools && python get.py && cd .. - tools/ci/prep-platformio.sh - if [ $? -ne 0 ]; then exit 1; fi - echo -e "travis_fold:end:prep_platformio" - - echo -e "travis_fold:start:test_platformio" - tools/ci/test-platformio.sh - if [ $? -ne 0 ]; then exit 1; fi - echo -e "travis_fold:end:test_platformio" -fi \ No newline at end of file diff --git a/tools/ci/deploy-release.sh b/tools/ci/deploy-release.sh deleted file mode 100644 index 9ec9458cec7..00000000000 --- a/tools/ci/deploy-release.sh +++ /dev/null @@ -1,248 +0,0 @@ -#!/bin/bash - - -json_escape () { - printf '%s' "$1" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))' - #printf '%s' "$1" | php -r 'echo json_encode(file_get_contents("php://stdin"));' -} - -set -e - -#Cmdline options -# -t: tag (*_RC* determines prerelease version, can be overriden be -p) -# -a: GitHub API access token -# -s: GitHub repository slug (user/repo) -# -p: prerelease true/false -# -f: files to upload (ie assets. delim = ';', must come quoted) -# -d: directory to upload (by adding dir contents to assets) -while getopts ":t:,:a:,:s:,:p:,:f:,:d:" opt; do - case $opt in - t) - varTagName=$OPTARG - echo "TAG: $varTagName" >&2 - ;; - a) - varAccessToken=$OPTARG - echo "ACCESS TOKEN: $varAccessToken" >&2 - ;; - s) - varRepoSlug=$OPTARG - echo "REPO SLUG: $varRepoSlug" >&2 - ;; - p) - varPrerelease=$OPTARG - echo "PRERELEASE: $varPrerelease" >&2 - ;; - f) - varAssets=$OPTARG - echo "ASSETS: $varAssets" >&2 - ;; - d) - varAssetsDir=$OPTARG - echo "ASSETS DIR: $varAssetsDir" >&2 - ;; - \?) - echo "Invalid option: -$OPTARG" >&2 - exit 1 - ;; - :) - echo "Option -$OPTARG requires an argument." >&2 - exit 1 - ;; - esac -done - -# use TravisCI env as default, if available -if [ -z $varTagName ] && [ ! -z $TRAVIS_TAG ]; then - varTagName=$TRAVIS_TAG -fi - -if [ -z $varTagName ]; then - echo "No tag name available => aborting" - exit 1 -fi - -#Check tag name for release/prerelease (prerelease tag contains '_RC' as for release-candidate. case-insensitive) -shopt -s nocasematch -if [ -z $varPrerelease ]; then - if [[ $varTagName == *-RC* ]]; then - varPrerelease=true - else - varPrerelease=false - fi -fi -shopt -u nocasematch - -# -# Prepare Markdown release notes: -################################# -# - annotated tags only, lightweight tags just display message of referred commit -# - tag's description conversion to relnotes: -# first 3 lines (tagname, commiter, blank): ignored -# 4th line: relnotes heading -# remaining lines: each converted to bullet-list item -# empty lines ignored -# if '* ' found as a first char pair, it's converted to '- ' to keep bulleting unified -echo -echo Preparing release notes -echo ----------------------- -echo "Tag's message:" - -relNotesRaw=`git show -s --format=%b $varTagName` -readarray -t msgArray <<<"$relNotesRaw" -arrLen=${#msgArray[@]} - -#process annotated tags only -if [ $arrLen > 3 ] && [ "${msgArray[0]:0:3}" == "tag" ]; then - ind=3 - while [ $ind -lt $arrLen ]; do - if [ $ind -eq 3 ]; then - releaseNotes="#### ${msgArray[ind]}" - releaseNotes+=$'\r\n' - else - oneLine="$(echo -e "${msgArray[ind]}" | sed -e 's/^[[:space:]]*//')" - - if [ ${#oneLine} -gt 0 ]; then - if [ "${oneLine:0:2}" == "* " ]; then oneLine=$(echo ${oneLine/\*/-}); fi - if [ "${oneLine:0:2}" != "- " ]; then releaseNotes+="- "; fi - releaseNotes+="$oneLine" - releaseNotes+=$'\r\n' - - #debug output - echo " ${oneLine}" - fi - fi - let ind=$ind+1 - done -fi - -echo "$releaseNotes" - -# - list of commits (commits.txt must exit in the output dir) -commitFile=$varAssetsDir/commits.txt -if [ -s "$commitFile" ]; then - - releaseNotes+=$'\r\n##### Commits\r\n' - - echo - echo "Commits:" - - IFS=$'\n' - for next in `cat $commitFile` - do - IFS=' ' read -r commitId commitMsg <<< "$next" - commitLine="- [$commitId](https://github.com/$varRepoSlug/commit/$commitId) $commitMsg" - echo " $commitLine" - - releaseNotes+="$commitLine" - releaseNotes+=$'\r\n' - done - rm -f $commitFile -fi - -# Check possibly existing release for current tag -echo -echo "Processing GitHub release record for $varTagName:" -echo "-------------------------------------------------" - -echo " - check $varTagName possible existence..." - -# (eg build invoked by Create New Release GHUI button -> GH default release pack created immediately including default assests) -HTTP_RESPONSE=$(curl -L --silent --write-out "HTTPSTATUS:%{http_code}" https://api.github.com/repos/$varRepoSlug/releases/tags/$varTagName?access_token=$varAccessToken) -if [ $? -ne 0 ]; then echo "FAILED: $? => aborting"; exit 1; fi - -HTTP_BODY=$(echo $HTTP_RESPONSE | sed -e 's/HTTPSTATUS\:.*//g') -HTTP_STATUS=$(echo $HTTP_RESPONSE | tr -d '\n' | sed -e 's/.*HTTPSTATUS://') -echo " ---> GitHub server HTTP response: $HTTP_STATUS" - -# if the release exists, append/update recent files to its assets vector -if [ $HTTP_STATUS -eq 200 ]; then - releaseId=$(echo $HTTP_BODY | jq -r '.id') - echo " - $varTagName release found (id $releaseId)" - - #Merge release notes and overwrite pre-release flag. all other attributes remain unchanged: - - # 1. take existing notes from server (added by release creator) - releaseNotesGH=$(echo $HTTP_BODY | jq -r '.body') - - # - strip possibly trailing CR - if [ "${releaseNotesGH: -1}" == $'\r' ]; then - releaseNotesTemp="${releaseNotesGH:0:-1}" - else - releaseNotesTemp="$releaseNotesGH" - fi - # - add CRLF to make relnotes consistent for JSON encoding - releaseNotesTemp+=$'\r\n' - - # 2. #append generated relnotes (usually commit oneliners) - releaseNotes="$releaseNotesTemp$releaseNotes" - - # 3. JSON-encode whole string for GH API transfer - releaseNotes=$(json_escape "$releaseNotes") - - # 4. remove extra quotes returned by python (dummy but whatever) - releaseNotes=${releaseNotes:1:-1} - - #Update current GH release record - echo " - updating release notes and pre-release flag:" - - curlData="{\"body\": \"$releaseNotes\",\"prerelease\": $varPrerelease}" - echo " $curlData" - echo - #echo "DEBUG: curl --data \"$curlData\" https://api.github.com/repos/$varRepoSlug/releases/$releaseId?access_token=$varAccessToken" - - curl --data "$curlData" https://api.github.com/repos/$varRepoSlug/releases/$releaseId?access_token=$varAccessToken - if [ $? -ne 0 ]; then echo "FAILED: $? => aborting"; exit 1; fi - - echo " - $varTagName release record successfully updated" - -#... or create a new release record -else - releaseNotes=$(json_escape "$releaseNotes") - releaseNotes=${releaseNotes:1:-1} - - echo " - release $varTagName not found, creating a new record:" - - curlData="{\"tag_name\": \"$varTagName\",\"target_commitish\": \"master\",\"name\": \"v$varTagName\",\"body\": \"$releaseNotes\",\"draft\": false,\"prerelease\": $varPrerelease}" - echo " $curlData" - - #echo "DEBUG: curl --data \"${curlData}\" https://api.github.com/repos/${varRepoSlug}/releases?access_token=$varAccessToken | jq -r '.id'" - releaseId=$(curl --data "$curlData" https://api.github.com/repos/$varRepoSlug/releases?access_token=$varAccessToken | jq -r '.id') - if [ $? -ne 0 ]; then echo "FAILED: $? => aborting"; exit 1; fi - - echo " - $varTagName release record successfully created (id $releaseId)" -fi - -# Assets defined by dir contents -if [ ! -z $varAssetsDir ]; then - varAssetsTemp=$(ls -p $varAssetsDir | grep -v / | tr '\n' ';') - for item in $(echo $varAssetsTemp | tr ";" "\n") - do - varAssets+=$varAssetsDir/$item; - varAssets+=';' - done -fi - -#Upload additional assets -if [ ! -z $varAssets ]; then - echo - echo "Uploading assets:" - echo "-----------------" - echo " Files to upload:" - echo " $varAssets" - echo - - curlAuth="Authorization: token $varAccessToken" - for filename in $(echo $varAssets | tr ";" "\n") - do - echo " - ${filename}:" - curl -X POST -sH "$curlAuth" -H "Content-Type: application/octet-stream" --data-binary @"$filename" https://uploads.github.com/repos/$varRepoSlug/releases/$releaseId/assets?name=$(basename $filename) - - if [ $? -ne 0 ]; then echo "FAILED: $? => aborting"; exit 1; fi - - echo - echo "OK" - echo - - done -fi diff --git a/tools/ci/prep-arduino-ide.sh b/tools/ci/prep-arduino-ide.sh deleted file mode 100755 index 90c8d397386..00000000000 --- a/tools/ci/prep-arduino-ide.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -pip install pyserial -wget -O arduino.tar.xz https://www.arduino.cc/download.php?f=/arduino-nightly-linux64.tar.xz -tar xf arduino.tar.xz -mv arduino-nightly $HOME/arduino_ide -mkdir -p $HOME/Arduino/libraries -mkdir -p $HOME/Arduino/hardware/espressif -cd $HOME/Arduino/hardware/espressif - -ln -s $TRAVIS_BUILD_DIR esp32 -cd esp32/tools -python get.py diff --git a/tools/ci/prep-platformio.sh b/tools/ci/prep-platformio.sh deleted file mode 100755 index dbcb444d25e..00000000000 --- a/tools/ci/prep-platformio.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -pip install -U https://github.com/platformio/platformio/archive/develop.zip && \ -python -m platformio platform install https://github.com/platformio/platform-espressif32.git#feature/stage && \ -sed -i 's/https:\/\/github\.com\/espressif\/arduino-esp32\.git/*/' ~/.platformio/platforms/espressif32/platform.json && \ -ln -s $TRAVIS_BUILD_DIR ~/.platformio/packages/framework-arduinoespressif32 diff --git a/tools/ci/test-arduino-ide.sh b/tools/ci/test-arduino-ide.sh deleted file mode 100755 index f902ce27214..00000000000 --- a/tools/ci/test-arduino-ide.sh +++ /dev/null @@ -1,170 +0,0 @@ -#!/bin/bash - -CHUNK_INDEX=$1 -CHUNKS_CNT=$2 -if [ "$#" -lt 2 ]; then - echo "Building all sketches" - CHUNK_INDEX=0 - CHUNKS_CNT=1 -fi -if [ "$CHUNKS_CNT" -le 0 ]; then - echo "Chunks count must be positive number" - exit 1 -fi -if [ "$CHUNK_INDEX" -ge "$CHUNKS_CNT" ]; then - echo "Chunk index must be less than chunks count" - exit 1 -fi - -export ARDUINO_BOARD_FQBN="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app,CPUFreq=240,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=none" - -export ARDUINO_IDE_PATH=$HOME/arduino_ide -export ARDUINO_USR_PATH=$HOME/Arduino - -export EXAMPLES_PATH=$TRAVIS_BUILD_DIR/libraries -export EXAMPLES_BUILD_DIR=$HOME/build.tmp -export EXAMPLES_CACHE_DIR=$HOME/cache.tmp -export EXAMPLES_BUILD_CMD="$ARDUINO_IDE_PATH/arduino-builder -compile -logger=human -core-api-version=\"10810\" -hardware \"$ARDUINO_IDE_PATH/hardware\" -hardware \"$ARDUINO_USR_PATH/hardware\" -tools \"$ARDUINO_IDE_PATH/tools-builder\" -built-in-libraries \"$ARDUINO_IDE_PATH/libraries\" -libraries \"$ARDUINO_USR_PATH/libraries\" -fqbn=$ARDUINO_BOARD_FQBN -warnings=\"all\" -build-cache \"$EXAMPLES_CACHE_DIR\" -build-path \"$EXAMPLES_BUILD_DIR\" -verbose" -export EXAMPLES_SIZE_BIN=$TRAVIS_BUILD_DIR/tools/xtensa-esp32-elf/bin/xtensa-esp32-elf-size - -function print_size_info() -{ - elf_file=$1 - - if [ -z "$elf_file" ]; then - printf "sketch iram0.text flash.text flash.rodata dram0.data dram0.bss dram flash\n" - return 0 - fi - - elf_name=$(basename $elf_file) - sketch_name="${elf_name%.*}" - # echo $sketch_name - declare -A segments - while read -a tokens; do - seg=${tokens[0]} - seg=${seg//./} - size=${tokens[1]} - addr=${tokens[2]} - if [ "$addr" -eq "$addr" -a "$addr" -ne "0" ] 2>/dev/null; then - segments[$seg]=$size - fi - done < <($EXAMPLES_SIZE_BIN --format=sysv $elf_file) - - total_ram=$((${segments[dram0data]} + ${segments[dram0bss]})) - total_flash=$((${segments[iram0text]} + ${segments[flashtext]} + ${segments[dram0data]} + ${segments[flashrodata]})) - printf "%-32s %-8d %-8d %-8d %-8d %-8d %-8d %-8d\n" $sketch_name ${segments[iram0text]} ${segments[flashtext]} ${segments[flashrodata]} ${segments[dram0data]} ${segments[dram0bss]} $total_ram $total_flash - return 0 -} - -function build_sketch() -{ - local sketch=$1 - echo -e "\n------------ Building $sketch ------------\n"; - rm -rf $EXAMPLES_BUILD_DIR/* - time ($EXAMPLES_BUILD_CMD $sketch >build.log) - local result=$? - if [ $result -ne 0 ]; then - echo "Build failed ($1)" - echo "Build log:" - cat build.log - return $result - fi - rm build.log - return 0 -} - -function count_sketches() -{ - local sketches=$(find $EXAMPLES_PATH -name *.ino) - local sketchnum=0 - rm -rf sketches.txt - for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - local sketchdirname=$(basename $sketchdir) - local sketchname=$(basename $sketch) - if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then - continue - fi; - if [[ -f "$sketchdir/.test.skip" ]]; then - continue - fi - echo $sketch >> sketches.txt - sketchnum=$(($sketchnum + 1)) - done - return $sketchnum -} - -function build_sketches() -{ - mkdir -p $EXAMPLES_BUILD_DIR - mkdir -p $EXAMPLES_CACHE_DIR - mkdir -p $ARDUINO_USR_PATH/libraries - mkdir -p $ARDUINO_USR_PATH/hardware - - local chunk_idex=$1 - local chunks_num=$2 - count_sketches - local sketchcount=$? - local sketches=$(cat 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 -e "Sketches: \n$sketches\n" - 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 - print_size_info >size.log - for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - local sketchdirname=$(basename $sketchdir) - local sketchname=$(basename $sketch) - if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then - #echo "Skipping $sketch, beacause it is not the main sketch file"; - continue - fi; - if [[ -f "$sketchdir/.test.skip" ]]; then - #echo "Skipping $sketch marked"; - continue - fi - sketchnum=$(($sketchnum + 1)) - if [ "$sketchnum" -le "$start_index" ]; then - #echo "Skipping $sketch index low" - continue - fi - if [ "$sketchnum" -gt "$end_index" ]; then - #echo "Skipping $sketch index high" - continue - fi - build_sketch $sketch - local result=$? - if [ $result -ne 0 ]; then - return $result - fi - print_size_info $EXAMPLES_BUILD_DIR/*.elf >>size.log - done - return 0 -} - -build_sketches $CHUNK_INDEX $CHUNKS_CNT - -if [ $? -ne 0 ]; then exit 1; fi diff --git a/tools/ci/test-platformio.sh b/tools/ci/test-platformio.sh deleted file mode 100755 index f699595b1c4..00000000000 --- a/tools/ci/test-platformio.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -python -m platformio ci --board esp32dev libraries/WiFi/examples/WiFiClient && \ -python -m platformio ci --board esp32dev libraries/WiFiClientSecure/examples/WiFiClientSecure && \ -python -m platformio ci --board esp32dev libraries/BluetoothSerial/examples/SerialToSerialBT && \ -python -m platformio ci --board esp32dev libraries/BLE/examples/BLE_server && \ -python -m platformio ci --board esp32dev libraries/AzureIoT/examples/GetStarted && \ -python -m platformio ci --board esp32dev libraries/ESP32/examples/Camera/CameraWebServer --project-option="board_build.partitions = huge_app.csv" -if [ $? -ne 0 ]; then exit 1; fi diff --git a/tools/esptool.py b/tools/esptool.py index 6bfa1f7b667..d6ceb6f9b39 100755 --- a/tools/esptool.py +++ b/tools/esptool.py @@ -60,7 +60,7 @@ "Check the README for installation instructions." % (sys.VERSION, sys.executable)) raise -__version__ = "2.6" +__version__ = "2.8-dev" MAX_UINT32 = 0xffffffff MAX_UINT24 = 0xffffff @@ -135,6 +135,15 @@ def byte(bitstr, index): basestring = str +def _mask_to_shift(mask): + """ Return the index of the least significant bit in the mask """ + shift = 0 + while mask & 0x1 == 0: + shift += 1 + mask >>= 1 + return shift + + def esp8266_function_only(func): """ Attribute for a function only supported on ESP8266 """ return check_supported_function(func, lambda o: o.CHIP_NAME == "ESP8266") @@ -180,6 +189,9 @@ class ESPLoader(object): ESP_READ_FLASH = 0xD2 ESP_RUN_USER_CODE = 0xD3 + # Flash encryption debug more command + ESP_FLASH_ENCRYPT_DATA = 0xD4 + # Maximum block sized for RAM and Flash writes, respectively. ESP_RAM_BLOCK = 0x1800 @@ -197,8 +209,11 @@ class ESPLoader(object): # Flash sector size, minimum unit of erase. FLASH_SECTOR_SIZE = 0x1000 + # This register happens to exist on both ESP8266 & ESP32 UART_DATA_REG_ADDR = 0x60000078 + UART_CLKDIV_MASK = 0xFFFFF + # Memory addresses IROM_MAP_START = 0x40200000 IROM_MAP_END = 0x40300000 @@ -467,8 +482,8 @@ def connect(self, mode='default_reset'): print('') # end 'Connecting...' line raise FatalError('Failed to connect to %s: %s' % (self.CHIP_NAME, last_error)) - """ Read memory address in target """ def read_reg(self, addr): + """ Read memory address in target """ # we don't call check_command here because read_reg() function is called # when detecting chip type, and the way we check for success (STATUS_BYTES_LENGTH) is different # for different chip types (!) @@ -477,11 +492,28 @@ def read_reg(self, addr): raise FatalError.WithResult("Failed to read register address %08x" % addr, data) return val - """ Write to memory address in target """ def write_reg(self, addr, value, mask=0xFFFFFFFF, delay_us=0): + """ Write to memory address in target + + Note: mask option is not supported by stub loaders, use update_reg() function. + """ return self.check_command("write target memory", self.ESP_WRITE_REG, struct.pack(' length: raise FatalError('Read more than expected') + digest_frame = self.read() if len(digest_frame) != 16: raise FatalError('Expected digest, got: %s' % hexify(digest_frame)) @@ -899,6 +940,22 @@ def write_status(self, new_status, num_bytes=2, set_non_volatile=False): self.run_spiflash_command(SPIFLASH_WRDI) + def get_crystal_freq(self): + # Figure out the crystal frequency from the UART clock divider + # Returns a normalized value in integer MHz (40 or 26 are the only supported values) + # + # The logic here is: + # - We know that our baud rate and the ESP UART baud rate are roughly the same, or we couldn't communicate + # - We can read the UART clock divider register to know how the ESP derives this from the APB bus frequency + # - Multiplying these two together gives us the bus frequency which is either the crystal frequency (ESP32) + # or double the crystal frequency (ESP8266). See the self.XTAL_CLK_DIVIDER parameter for this factor. + uart_div = self.read_reg(self.UART_CLKDIV_REG) & self.UART_CLKDIV_MASK + est_xtal = (self._port.baudrate * uart_div) / 1e6 / self.XTAL_CLK_DIVIDER + norm_xtal = 40 if est_xtal > 33 else 26 + if abs(norm_xtal - est_xtal) > 1: + print("WARNING: Detected crystal freq %.2fMHz is quite different to normalized freq %dMHz. Unsupported crystal in use?" % (est_xtal, norm_xtal)) + return norm_xtal + def hard_reset(self): self._setRTS(True) # EN->LOW time.sleep(0.1) @@ -943,6 +1000,10 @@ class ESP8266ROM(ESPLoader): SPI_W0_OFFS = 0x40 SPI_HAS_MOSI_DLEN_REG = False + UART_CLKDIV_REG = 0x60000014 + + XTAL_CLK_DIVIDER = 2 + FLASH_SIZES = { '512KB':0x00, '256KB':0x10, @@ -957,6 +1018,11 @@ class ESP8266ROM(ESPLoader): BOOTLOADER_FLASH_OFFSET = 0 + MEMORY_MAP = [[0x3FF00000, 0x3FF00010, "DPORT"], + [0x3FFE8000, 0x40000000, "DRAM"], + [0x40100000, 0x40108000, "IRAM"], + [0x40201010, 0x402E1010, "IROM"]] + def get_efuses(self): # Return the 128 bits of ESP8266 efuse as a single Python integer return (self.read_reg(0x3ff0005c) << 96 | @@ -1055,6 +1121,7 @@ class ESP32ROM(ESPLoader): """ CHIP_NAME = "ESP32" + IMAGE_CHIP_ID = 0 IS_STUB = False DATE_REG_VALUE = 0x15122500 @@ -1070,9 +1137,15 @@ class ESP32ROM(ESPLoader): SPI_REG_BASE = 0x60002000 EFUSE_REG_BASE = 0x6001a000 + DR_REG_SYSCON_BASE = 0x3ff66000 + SPI_W0_OFFS = 0x80 SPI_HAS_MOSI_DLEN_REG = True + UART_CLKDIV_REG = 0x3ff40014 + + XTAL_CLK_DIVIDER = 1 + FLASH_SIZES = { '1MB':0x00, '2MB':0x10, @@ -1085,9 +1158,77 @@ class ESP32ROM(ESPLoader): OVERRIDE_VDDSDIO_CHOICES = ["1.8V", "1.9V", "OFF"] + MEMORY_MAP = [[0x3F400000, 0x3F800000, "DROM"], + [0x3F800000, 0x3FC00000, "EXTRAM_DATA"], + [0x3FF80000, 0x3FF82000, "RTC_DRAM"], + [0x3FF90000, 0x40000000, "BYTE_ACCESSIBLE"], + [0x3FFAE000, 0x40000000, "DRAM"], + [0x3FFAE000, 0x40000000, "DMA"], + [0x3FFE0000, 0x3FFFFFFC, "DIRAM_DRAM"], + [0x40000000, 0x40070000, "IROM"], + [0x40070000, 0x40078000, "CACHE_PRO"], + [0x40078000, 0x40080000, "CACHE_APP"], + [0x40080000, 0x400A0000, "IRAM"], + [0x400A0000, 0x400BFFFC, "DIRAM_IRAM"], + [0x400C0000, 0x400C2000, "RTC_IRAM"], + [0x400D0000, 0x40400000, "IROM"], + [0x50000000, 0x50002000, "RTC_DATA"]] + + """ Try to read the BLOCK1 (encryption key) and check if it is valid """ + + def is_flash_encryption_key_valid(self): + + """ Bit 0 of efuse_rd_disable[3:0] is mapped to BLOCK1 + this bit is at position 16 in EFUSE_BLK0_RDATA0_REG """ + word0 = self.read_efuse(0) + rd_disable = (word0 >> 16) & 0x1 + + # reading of BLOCK1 is NOT ALLOWED so we assume valid key is programmed + if rd_disable: + return True + else: + """ reading of BLOCK1 is ALLOWED so we will read and verify for non-zero. + When ESP32 has not generated AES/encryption key in BLOCK1, the contents will be readable and 0. + If the flash encryption is enabled it is expected to have a valid non-zero key. We break out on + first occurance of non-zero value """ + key_word = [0] * 7 + for i in range(len(key_word)): + key_word[i] = self.read_efuse(14 + i) + # key is non-zero so break & return + if key_word[i] != 0: + return True + return False + + """ For flash encryption related commands we need to make sure + user has programmed all the relevant efuse correctly so at + the end of write_flash_encrypt esptool will verify the values + of flash_crypt_config to be non zero if they are not read + protected. If the values are zero a warning will be printed + """ + + def get_flash_crypt_config(self): + """ bit 3 in efuse_rd_disable[3:0] is mapped to flash_crypt_config + this bit is at position 19 in EFUSE_BLK0_RDATA0_REG """ + word0 = self.read_efuse(0) + rd_disable = (word0 >> 19) & 0x1 + + if rd_disable == 0: + """ we can read the flash_crypt_config efuse value + so go & read it (EFUSE_BLK0_RDATA5_REG[31:28]) """ + word5 = self.read_efuse(5) + word5 = (word5 >> 28) & 0xF + return word5 + else: + # if read of the efuse is disabled we assume it is set correctly + return 0xF + def get_chip_description(self): word3 = self.read_efuse(3) - chip_ver_rev1 = (word3 >> 15) & 0x1 + word5 = self.read_efuse(5) + apb_ctl_date = self.read_reg(self.DR_REG_SYSCON_BASE + 0x7C) + rev_bit0 = (word3 >> 15) & 0x1 + rev_bit1 = (word5 >> 20) & 0x1 + rev_bit2 = (apb_ctl_date >> 31) & 0x1 pkg_version = (word3 >> 9) & 0x07 chip_name = { @@ -1097,7 +1238,16 @@ def get_chip_description(self): 5: "ESP32-PICO-D4", }.get(pkg_version, "unknown ESP32") - return "%s (revision %d)" % (chip_name, chip_ver_rev1) + chip_revision = 0 + if rev_bit0: + if rev_bit1: + if rev_bit2: + chip_revision = 3 + else: + chip_revision = 2 + else: + chip_revision = 1 + return "%s (revision %d)" % (chip_name, chip_revision) def get_chip_features(self): features = ["WiFi"] @@ -1298,11 +1448,11 @@ def __init__(self): self.elf_sha256_offset = 0 def load_common_header(self, load_file, expected_magic): - (magic, segments, self.flash_mode, self.flash_size_freq, self.entrypoint) = struct.unpack(' 16: @@ -1328,16 +1478,19 @@ def warn_if_unusual_segment(self, offset, size, is_irom_segment): def maybe_patch_segment_data(self, f, segment_data): """If SHA256 digest of the ELF file needs to be inserted into this segment, do so. Returns segment data.""" segment_len = len(segment_data) - file_pos = f.tell() + file_pos = f.tell() # file_pos is position in the .bin file if self.elf_sha256_offset >= file_pos and self.elf_sha256_offset < file_pos + segment_len: - # SHA256 digest needs to be patched into this segment, - # calculate offset of the digest inside the segment. + # SHA256 digest needs to be patched into this binary segment, + # calculate offset of the digest inside the binary segment. patch_offset = self.elf_sha256_offset - file_pos # Sanity checks if patch_offset < self.SEG_HEADER_LEN or patch_offset + self.SHA256_DIGEST_LEN > segment_len: - raise FatalError('Can not place SHA256 digest on segment boundary' + + raise FatalError('Cannot place SHA256 digest on segment boundary' + '(elf_sha256_offset=%d, file_pos=%d, segment_size=%d)' % (self.elf_sha256_offset, file_pos, segment_len)) + if segment_data[patch_offset:patch_offset + self.SHA256_DIGEST_LEN] != b'\x00' * self.SHA256_DIGEST_LEN: + raise FatalError('Contents of segment at SHA256 digest offset 0x%x are not all zero. Refusing to overwrite.' % + self.elf_sha256_offset) assert(len(self.elf_sha256) == self.SHA256_DIGEST_LEN) # offset relative to the data part patch_offset -= self.SEG_HEADER_LEN @@ -1386,12 +1539,12 @@ def is_irom_addr(self, addr): return ESP8266ROM.IROM_MAP_START <= addr < ESP8266ROM.IROM_MAP_END def get_irom_segment(self): - irom_segments = [s for s in self.segments if self.is_irom_addr(s.addr)] - if len(irom_segments) > 0: - if len(irom_segments) != 1: - raise FatalError('Found %d segments that could be irom0. Bad ELF file?' % len(irom_segments)) - return irom_segments[0] - return None + irom_segments = [s for s in self.segments if self.is_irom_addr(s.addr)] + if len(irom_segments) > 0: + if len(irom_segments) != 1: + raise FatalError('Found %d segments that could be irom0. Bad ELF file?' % len(irom_segments)) + return irom_segments[0] + return None def get_non_irom_segments(self): irom_segment = self.get_irom_segment() @@ -1440,6 +1593,9 @@ def save(self, basename): self.append_checksum(f, checksum) +ESP8266ROM.BOOTLOADER_IMAGE = ESP8266ROMFirmwareImage + + class ESP8266V2FirmwareImage(BaseFirmwareImage): """ 'Version 2' firmware image, segments loaded by software bootloader stub (ie Espressif bootloader or rboot) @@ -1558,7 +1714,7 @@ class ESP32FirmwareImage(BaseFirmwareImage): # to be set to this value so ROM bootloader will skip it. WP_PIN_DISABLED = 0xEE - EXTENDED_HEADER_STRUCT_FMT = "B" * 16 + EXTENDED_HEADER_STRUCT_FMT = " flash_end: - raise FatalError(("File %s (length %d) at offset %d will not fit in %d bytes of flash. " + - "Use --flash-size argument, or change flashing address.") - % (argfile.name, argfile.tell(), address, flash_end)) - argfile.seek(0) + if args.flash_size != 'keep': # TODO: check this even with 'keep' + flash_end = flash_size_bytes(args.flash_size) + for address, argfile in args.addr_filename: + argfile.seek(0,2) # seek to end + if address + argfile.tell() > flash_end: + raise FatalError(("File %s (length %d) at offset %d will not fit in %d bytes of flash. " + + "Use --flash-size argument, or change flashing address.") + % (argfile.name, argfile.tell(), address, flash_end)) + argfile.seek(0) if args.erase_all: erase_flash(esp, args) + if args.encrypt and args.compress: + print('\nWARNING: - compress and encrypt options are mutually exclusive ') + print('Will flash uncompressed') + args.compress = False + for address, argfile in args.addr_filename: if args.no_stub: print('Erasing flash...') - image = pad_to(argfile.read(), 4) + image = pad_to(argfile.read(), 32 if args.encrypt else 4) if len(image) == 0: print('WARNING: File %s is empty' % argfile.name) continue @@ -2159,7 +2375,10 @@ def write_flash(esp, args): else: # Pad the last block block = block + b'\xff' * (esp.FLASH_WRITE_SIZE - len(block)) - esp.flash_block(block, seq) + if args.encrypt: + esp.flash_encrypt_block(block, seq) + else: + esp.flash_block(block, seq) image = image[esp.FLASH_WRITE_SIZE:] seq += 1 written += len(block) @@ -2173,17 +2392,19 @@ def write_flash(esp, args): if t > 0.0: speed_msg = " (%.1f kbit/s)" % (written / t * 8 / 1000) print('\rWrote %d bytes at 0x%08x in %.1f seconds%s...' % (written, address, t, speed_msg)) - try: - res = esp.flash_md5sum(address, uncsize) - if res != calcmd5: - print('File md5: %s' % calcmd5) - print('Flash md5: %s' % res) - print('MD5 of 0xFF is %s' % (hashlib.md5(b'\xFF' * uncsize).hexdigest())) - raise FatalError("MD5 of file does not match data in flash!") - else: - print('Hash of data verified.') - except NotImplementedInROMError: - pass + + if not args.encrypt: + try: + res = esp.flash_md5sum(address, uncsize) + if res != calcmd5: + print('File md5: %s' % calcmd5) + print('Flash md5: %s' % res) + print('MD5 of 0xFF is %s' % (hashlib.md5(b'\xFF' * uncsize).hexdigest())) + raise FatalError("MD5 of file does not match data in flash!") + else: + print('Hash of data verified.') + except NotImplementedInROMError: + pass print('\nLeaving...') @@ -2207,11 +2428,12 @@ def image_info(args): print('Image version: %d' % image.version) print('Entry point: %08x' % image.entrypoint if image.entrypoint != 0 else 'Entry point not set') print('%d segments' % len(image.segments)) - print + print() idx = 0 for seg in image.segments: idx += 1 - print('Segment %d: %r' % (idx, seg)) + seg_name = ", ".join([seg_range[2] for seg_range in image.ROM_LOADER.MEMORY_MAP if seg_range[0] <= seg.addr < seg_range[1]]) + print('Segment %d: %r [%s]' % (idx, seg, seg_name)) calc_checksum = image.calculate_checksum() print('Checksum: %02x (%s)' % (image.checksum, 'valid' if image.checksum == calc_checksum else 'invalid - calculated %02x' % calc_checksum)) @@ -2249,6 +2471,7 @@ def elf2image(args): if args.chip == 'esp32': image = ESP32FirmwareImage() image.secure_pad = args.secure_pad + image.min_rev = int(args.min_rev) elif args.version == '1': # ESP8266 image = ESP8266ROMFirmwareImage() else: @@ -2397,7 +2620,8 @@ def main(custom_commandline=None): Main function for esptool custom_commandline - Optional override for default arguments parsing (that uses sys.argv), can be a list of custom arguments - as strings. + as strings. Arguments and their values need to be added as individual items to the list e.g. "-b 115200" thus + becomes ['-b', '115200']. """ parser = argparse.ArgumentParser(description='esptool.py v%s - ESP8266 ROM Bootloader Utility' % __version__, prog='esptool') @@ -2483,6 +2707,11 @@ def add_spi_flash_subparsers(parent, is_elf2image): extra_keep_args = [] if is_elf2image else ['keep'] auto_detect = not is_elf2image + if auto_detect: + extra_fs_message = ", detect, or keep" + else: + extra_fs_message = "" + parent.add_argument('--flash_freq', '-ff', help='SPI Flash frequency', choices=extra_keep_args + ['40m', '26m', '20m', '80m'], default=os.environ.get('ESPTOOL_FF', '40m' if is_elf2image else 'keep')) @@ -2490,12 +2719,15 @@ def add_spi_flash_subparsers(parent, is_elf2image): choices=extra_keep_args + ['qio', 'qout', 'dio', 'dout'], default=os.environ.get('ESPTOOL_FM', 'qio' if is_elf2image else 'keep')) parent.add_argument('--flash_size', '-fs', help='SPI Flash size in MegaBytes (1MB, 2MB, 4MB, 8MB, 16M)' - ' plus ESP8266-only (256KB, 512KB, 2MB-c1, 4MB-c1)', + ' plus ESP8266-only (256KB, 512KB, 2MB-c1, 4MB-c1)' + extra_fs_message, action=FlashSizeAction, auto_detect=auto_detect, default=os.environ.get('ESPTOOL_FS', 'detect' if auto_detect else '1MB')) add_spi_connection_arg(parent) - parser_write_flash = subparsers.add_parser('write_flash', help='Write a binary blob to flash') + parser_write_flash = subparsers.add_parser( + 'write_flash', + help='Write a binary blob to flash') + parser_write_flash.add_argument('addr_filename', metavar='
', help='Address followed by binary filename, separated by space', action=AddrFilenamePairAction) parser_write_flash.add_argument('--erase-all', '-e', @@ -2506,6 +2738,10 @@ def add_spi_flash_subparsers(parent, is_elf2image): parser_write_flash.add_argument('--no-progress', '-p', help='Suppress progress output', action="store_true") parser_write_flash.add_argument('--verify', help='Verify just-written data on flash ' + '(mostly superfluous, data is read back during flashing)', action='store_true') + parser_write_flash.add_argument('--encrypt', help='Encrypt before write ', + action='store_true') + parser_write_flash.add_argument('--ignore-flash-encryption-efuse-setting', help='Ignore flash encryption efuse settings ', + action='store_true') compress_args = parser_write_flash.add_mutually_exclusive_group(required=False) compress_args.add_argument('--compress', '-z', help='Compress data in transfer (default unless --no-stub is specified)',action="store_true", default=None) @@ -2534,6 +2770,7 @@ def add_spi_flash_subparsers(parent, is_elf2image): parser_elf2image.add_argument('input', help='Input ELF file') parser_elf2image.add_argument('--output', '-o', help='Output filename prefix (for version 1 image), or filename (for version 2 single image)', type=str) parser_elf2image.add_argument('--version', '-e', help='Output image version', choices=['1','2'], default='1') + parser_elf2image.add_argument('--min-rev', '-r', help='Minimum chip revision', choices=['0','1','2','3'], default='0') parser_elf2image.add_argument('--secure-pad', action='store_true', help='Pad image so once signed it will end on a 64KB boundary. For ESP32 images only.') parser_elf2image.add_argument('--elf-sha256-offset', help='If set, insert SHA256 hash (32 bytes) of the input ELF file at specified offset in the binary.', type=arg_auto_int, default=None) @@ -2658,12 +2895,14 @@ def add_spi_flash_subparsers(parent, is_elf2image): print("%s failed to connect: %s" % (each_port, err)) esp = None if esp is None: - raise FatalError("All of the %d available serial ports could not connect to a Espressif device." % len(ser_list)) + raise FatalError("Could not connect to an Espressif device on any of the %d available serial ports." % len(ser_list)) print("Chip is %s" % (esp.get_chip_description())) print("Features: %s" % ", ".join(esp.get_chip_features())) + print("Crystal is %dMHz" % esp.get_crystal_freq()) + read_mac(esp, args) if not args.no_stub: @@ -2692,7 +2931,8 @@ def add_spi_flash_subparsers(parent, is_elf2image): if hasattr(args, "flash_size"): print("Configuring flash size...") detect_flash_size(esp, args) - esp.flash_set_parameters(flash_size_bytes(args.flash_size)) + if args.flash_size != 'keep': # TODO: should set this even with 'keep' + esp.flash_set_parameters(flash_size_bytes(args.flash_size)) try: operation_func(esp, args) @@ -2775,6 +3015,7 @@ def __call__(self, parser, namespace, values, option_string=None): known_sizes.update(ESP32ROM.FLASH_SIZES) if self._auto_detect: known_sizes['detect'] = 'detect' + known_sizes['keep'] = 'keep' if value not in known_sizes: raise argparse.ArgumentError(self, '%s is not a known flash size. Known sizes: %s' % (value, ", ".join(known_sizes.keys()))) setattr(namespace, self.dest, value) @@ -2846,104 +3087,105 @@ def __call__(self, parser, namespace, values, option_string=None): # Binary stub code (see flasher_stub dir for source & details) ESP8266ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -eNrNPXt/00a2X8WSQ0iCoRpJ1iMNxXaCeRS2ATYBdtNtpJEE5ZZuYvzbUJZ+96vzmhnJDoG+7v0j1CNpZs6c9zlzZvrf68v6/fL67qC8fvK+yE7eq+DkfRBM2n/Uyfumgb/5HB51/7L2r6nvfHd/+qDtF7d/JXx6\ -p32ruVHfoc8yp1vTftnkMMuEvqQXp70J1Prfyh2poT8DkO7ORDP0oLadJmuXc/I+1zd4HUUgv9pprzsDxw7UZkCGpIOJXkOGKzvY6iBosO3A2hIjqxCsFw6AQCPTO4dG7TRyg/jYeQOdVWmHLoKTRQ85mQHhZCk/\ -D9t/aqehQmcI7YBRBk5DNWYRe+3jnAEKXFCBWEXlQBc40AWdl5rmMvOosYMi1eWBIHBYDxsye6mFRi3hs8xpFLbxAntNDpDdJ6NH+J/ga/zP+/uGax7yrzJ+wL+0vsW/VDtPHXKjynL89do8awepZOK8ha9G5p48\ -2hTIeEivHb2kteVtz0IR70MX1f7WgV8MfaQjrTss9tunYTFrxw+LKcxXtMM1YXGHJKhOaDRtMAVTIPraf8qQ8QhYiuc9AQwApvBbP4WvMp420zsedIB5W4qUEXTyhHDtQyUsoeThzgjmH9CoGlATypSyljFNXeVr\ -oAVCNQ1jI1BmLCBMGMQD8wBHxhEHPFzUH46fh5/7vH2Yo6RPCdCmeSI/zuUHryUsGUIeTFdr1pLXjJl8jJgZGuAzQotK3kk3QVjmICzqLpaeqtCfAgv5/BEAoTfw2Xj2ZD8s/E1kpyWwaZRCB0Ba4ko//En/SGYL\ -QUZ9YL3AHzQz6LhlabmF6C58wzZMzBacJ/v8WzMyQPV1kSHsFAOH+zBRyLyQ3SUNinbILNx3YaLBlBrAj0GL15TVcZMSU6uUmArwHSieq65p0KK4BBiBljiuyx9ZAnLNnGjRjEzTGok8ItgAqxlqqjR80gjACUMC\ -gCfvhg1+PP9enuyf/NwM5dNHPCf0qVzyNPvY6xx/P3Omi5hREjIFrjrNO8AFyQeCDLDcvHOGcBaJH4NipF7z93a00hlt/haet7TPWA8r3UNETnNtNawlcHUT+RgetID8TCM3PThvWSRkqe2iXABm8tx3Hr4UqEKH\ -rpWCL1Q0aidcyrOAnrV/GUD7a48XumTNkmvuu6j7rv0NwjR2caUqMA9gFeGLU9ZxibGxDWMunBfy7tzVRotVFqzbL+sKXBUyyVny1hjv0RQ6/bvf6ZjsiCpIuVWgk3Dxt+irTD8eoHd2/AwMZvumIKGr1Zh1G6ws\ -dvlwAFKHCvvVynRPCZ11QHNpnOsr/pF+Q2uAOdAurg5Ny/jhsmUka5dxzIamBjo+tyQAH6YKRbQ3DcJfCLM3jHkhSNkIRSuhydcrr/bplU7+5hJ7Uz6ZP0Zt/sjzHNvgAhIK3zniPr/D88FYMU+nwnYU8t8+Z6C5\ -aIFvaCxAUmvTpy5+PcKhHS5kgQuccdsP6tQVZPSOshHov6fEHbohAjRkkIz65GFysCDI/OI11M3czlQX+zNLeVhfXU98GC69BeM/ZejGpbgJM/6BquoINL8o4fT0CI3RATw8PBjAB+iSTKIBwKXFrGglax6QY5BH\ -8xsOXhrmIIsGBzcqiU6WoFLM2+yYtVoWsh5C5OhkYLVVRiqE2GLDUhh9a+Sa+cBw33f41ZbwHclsh/WCZFtYr++oUW/ggq3uNJb9SU+ptNPNMO2mMy+OPCUmAIxYgr8nqmmddtml0f8GV3Pcw2D+mjyWJk1G0H1A\ -MZQLU24YhTz+nPVpgHDutI2c3fbsW59awXjn+YC+0sgzoK2alwQafhDNOWIcGyXLq88cMassllYRSgpK3GyBGOSmCgagw8dL9q+xqcfvHD9D3IgmZ6Vk9VirsHVh/DSZokGfrDVSEYr/TOhNMwdxU1pTXaHS3BTm\ -THwM1IVdgPGGKeGxJSshN4hDsWk40QM2puQK2qFF0+jEDoeygXhm56ku+4uCgKKWh9aXhccoU4MIXbwRUGYwBLEIRwy9wzV2vNvw8iYGqvA+6r8HLLcP64yd9qb/ARO0dGNEnJ4mjmbwb/zi5ARctf8w6ZnpqMd6\ -rzNClzMaALoAKtQvyLx3/8k+f2LTDZ/rV/uoykmdWrVZ3GA2rdnBALaNPQoxmnpqcV5CyBOQl0NcCiRCvop80DrhwrtRFtcoimarfD1lBSyyF+IHYQHTjB+z0x5643PyKWGiPPRunH3Ltrw4IAyD/14V/1MW2zjI\ -aPKCI9aWf4qGhFqN5+DmxRcU3BK7/UwAwOC1XoyoVwYEUuOtn2C2YnNRbOCoO3vPQL9+BKmED+LXoHNAuZaRlRVMdMSK9EVTk1XaoveIDlTm3kfmZVcRAzvlJDXw3yzMQVjafwrom97ZxcB64y11aX9uso8DxqTF\ -CziHehhgfst7x+jSbEPRpj8ovyeEQViIzl8ixg1mIEVcg6BSTsJ7S6PAonSTs0Ob8F/AD2iwuetGhTYn1em7Aj/6BzVMvjdicFwJwpEXtLJrhymu7NSuLIhemhWJt26WkdhlgJB11pHLOqJ+lk6kI/BeOH009vGO\ -+RHEChGkxcLXbC2CayBIb/xZETwt4rL4CqgGCoK5GRhCraoIovvMC556celhJy8inichrElLDRpiTa3/cziIRVizAQZeh3+HILs8kjj8/DEzF+arMNbBrMCr1FIlGE8mkAUSfySZgBhFQQOspOc8VDLv08LbhbFH\ -+znhvX1fxX00MkWa5PYdJOy2VUnmpWFAZlt/sMUiq2lxgY4AH02dl8K9NIwuaD5D51Do6svyeI4gcXICku0lcvLvaiKqHIL4GuQoK5kpwQHFeP78GqGzNbIb7VLKdOBNYUkpSV8dTclCYqqlOvaHaJ43UDFUe4iB\ -a5/AQG4wsM0Og352DPa04E5xL8No+PtPWPdcFs3KHNbBOb4JLxdopD4C5QaEKRVYv1glj8m5aYAzIZHWrn546eoXsnQMInAcfUwWqIkdhWLWnP0ptAa1g5avARccWBesGC6jfuPv+sBkMzJRhtAcX9bZVFbeJ9Pe\ -9PP5XjEAHFdTdmexrWkENLKNq6E9sFfw/ZSyTU1llN0b/6EvWCKoeWrr0U4ZxdWb6GHk78M3BtkeOzswMqSqaGQtIwseBLUK4GmSeddZxMwx50nBEVjmfhu5gJqkhFnT+hvLr8OT5a7rgyjyHpoq8DEtkrOhQadZ\ -ryBx9G4umW1JYQHPXSVxPZ7bi47JwII8/eXyRp0bx1mrcUdmiR7HpsNjlvGcGDYI9vbnxAFBuKpXWoWSA/TAyMHCg/CqbBZ3BcAj6wiSHXpMjSrYB6fhdIiuw3VyryABhoSonLxeRM9qvWb+DOfPzPxz4T5H5Y3A\ -fVpKaPTBOv5r6DaiHCPMV2aXSBXSCrKh9cLbPgTQNUZCH+CfC0rKBgqSbCG0EmklN0HcweXXgIOUTPgC/a6eFdc1iam14gsvFOtNdhtsOMyoPxydNZwawh2QjPMaAG3YSuBiZa+jtx7ci4o4qYoMsmmDpSzxLFf5\ -r0CIRuye56gSZvAsFL9z/IlFlfmaRUnSJNu5AO+F122X2K64XTdgLp1J0ny2L8wVXRB/YGSswzPaTQzYFc3jmSROS58jxSb1Ze9CNp2AznrZD41n901XkrMskyHGIW3z1dkuR+yQAUllvGbn/uLAdmbXHdOIGAoo\ -J22XeL+givR9I2+fadFXfBrMWoue0bqrZ662bdlKYuC3+jO16BnvFVGT5N5Z45TJjMOFOBz4WmoyZxIDwmoMQoOBTa+ucRHuIy9+B8M9jAab0B02pyCxg0ajTEBdK++fFpI2KEbQn+LWdYdH/9tnUKFSy4JdrzmQ\ -FIuxCrd/kxMGdvCYDIwO/x+YBm8frbLqM2WL7mBjZ2M6IQxZT9Qaa+Omtoj3dtCm+5h54T0DpSMkDQgn5u7UeeZS5WwBTI1CPjl7D/ZpAf7vC4hD1IHEO63BUi7ZFgXWLajDVd1ycn0KOdaKlr1zct1JcwXq234H\ -ghmphEMiUDvbM9qhw20jNV9lkFYOVcseW5AoRfWM5SA8VRaCcCq/uImQ37K20GUmFL2xS3UAfgf3riJXC6GUBLOhMPjBTNPPFohbZAYxro9lHuAzBalU9dg1wewAYJJngehtWwVp9DwDWwktCCVzyOA15Dyhwt0m\ -YufFAe91QVJLloueWLLBlsOgW3FNjMb5l7u+wDEg7Y0WHsQZkwofyW9UsKmm1OWWOvJY1+i85K29XGZGCuZFxrkEQWLygiRHYaEG7qpHklyfFShfB1AIEC2K7CwdcNJfqbBIQy+ZeSnCES+8JCy2JtFg5mVn58jx\ -B4simRXZPcryVJzwANHN0lSd3ael5MGBzeBPJmpWbNmwEyHMeNMQS1uA3Qj2WbugyTsYYOZtAXWi2XNoLchyN7gXnFLGMktMph26BWdgCCcX2JlJDL5ChlP6OMxgZlJzdZBPBSWsWVCJhO3iz2DxZwfA/wtKeTXN\ -5B4yKzzF8dtAfdkuC2aKJZsAEtTC7f8d9bkzV4tIQN5Fi7z2Z6CmLaJB9LUxZyk7l8XCS4ExsjOkAKbmgyALWDpzBGKCfHQWURFJHj6zmjDPXSFRuc0El1pqULybm9s2gV6kdp84c9xRUNUVb73Tt7InDTl8gLxI\ -fHm1LUnjjNi/Rsc0Pufcpt4ZnvmMOLPNw9yB9RiyR60mD5QIzT1KNsuevOFgke50Qju2KT/DiOmaXYwpQ9LkKtBitimWwnIW/ZHcSMfeYhYHpEYHkNEJ4oeA5SIiZIc2/QesX0eSpZzdaP0f8HjRg4s5CE4k0Nzb\ -cI3X1YE7xmcRx+75Xxi7W8KHTgyaOqFEupLam9naiay82ZkjsuUz7P5s4KzDAU18g6ASK6uAhYBvXRb6t8s/ocs/qLKCAfMPVQcEuYKxUegTrEQIiOBYTaKZG2ImvCrFB4kt9cHPNNT30TTQ5D5nOpH6yFyPuXwn\ -4byB3ZqAaLOVw01TCkEvoo5T5+yoo1etIu8lQIkZUU25EvQUlOQGNG1e27/czGGt3owqspoAQzNQp1l0Goqo8AYRslj2VgwJwHupP6e0uDP/xLROSaikuVv0mO0O40f5BWfs7gj7f27OSunhMXFEFq36iYb90/Xs\ -P1/D+5rDhID8h41VKbAcGGRGItLbMJX3N1or0TKn7po2XbOCd2lUjmNdwFiruAC4LoDkF7DCnQsPdeR0hHy9+ZDGWHYYgxQ78QYPqLSowQbV7FJNkEkOdg9CwpG6Itp+RiuxPl3rxVG0/aFx/bR5Pyg4J1eo0TMk\ -ksJQT4U7ROJEKoea5pWzFZDI8ld46RkH202joIpWe7wFoFdT/biKQH3Th7wF2yNnouGSCTVjoKIP4C8pRa9wUw9Rp9L+IKvRN5d3NGDFMGteRjn9wt0GiAPKLareQwVQok/7TCoY2SzWyYyr8DSZCDQ8kYhQ0hHe\ -7cNcjOlQNO53dsOzya1WccwteFPBOdfMlphMB13ZsbHln2Jj51cbWNatWOsa0w7lbzWwzWcb2GtfomHe8R4me0boWVbrjGzyFxrZ7I83sqxSwlU7O6XiGYd3JmLiLO9gMDQ4FfuaUFG7Oj3lHGZiqssxsfaRjGDm\ -0F2Vw47hQ+V2+gp9WrS6u5DgKZoJ+KWA1zwR4s9N2cAa+9rNjQwcVUklHa/EbZ0/sEWHpvBHW9uCEWRwRa61dHO8yHeumwzbyimEcLkpInV4QioMhoPL+GKFNhxOloGhzZTPApS7fodMgUOmQLWkIakpIivBQAlV\ -bnwkYem7OkHiyuHCEk5MUFN+QLlcFc5n4v8IfaS2MHjr7GBeQiiuADXVaBv9sAMMXj5bi0/UaIONz8fnbAWf57/Cyh76l8Yk8FhhvUIbbD1gtDZOeXaRmvyJKu99dDy8FFd8JijEcrUzDCg/wGwKtHZpMP3BOJbW\ -u/Qx01OhFUEXDvx/zCs0fjtjeNexz3EHv5Mefk0RxdFbSygSg1BGUjdg4yJ5JdQj6W6YX6DcqCwEw5jw3Gm8D6I5Gtqm56rxDe89vHgDNjJISnCVVLLJo5fVAQMh2woBynh2mcIeoqfKe9gFm/E8gvK6pvqURxj2\ -dLVNd4d9XW1cnZu8N9Z3D1m3kuYOOq5h0XEHo44nKCrZSe+6Lt0aj09yRa6/QBSLJere7TkKOtlBN2BXqIHxkrGjUA8ZNJKI1FwbqNTphBU61eOf/ijOQPyKnYFw5uQPHa9ApadYQ3rPim6G9HWqs6w5kHXswPIe\ -AoxutE324BS59j4sDPguiN8cYMrNZFnyWPTNAYcupb4RAf5pgynpOgKkfDo85lrUK9ksYzYroNyw5jDHcFj+B3BYn7eCdb4B4s45fFCNP+kblK5v8PhS3yCecB19gYW065XlOYnk5Qw1cxmq613SoYVWX0piz3oI\ -oAxVReMieyQmAhcMJZYjyD1kjrjUPdwXesdrPIRLFOOUdD0tDy3z7gFurcyKjSnxAbwDPbAbZ1jfB5GxSl7bgwtlNft8LlspJesyWskOLjoafyyvlVerslegx/RiRYmlnQ6UYXBUmWwGWnMneD5zDBAiDuiOxw+K\ -EuPngKoedRvBwbEAzCwVpxgCneHYGA2ExU6wP3guWvDw7oCcsp2De3CQCGtZQ6ljxSFGzyg3jmdP957B85iKfgK9kZfzH9YTxtnSr/MFbIyYOH+EqXrc81Z2NHK9gp2hE92r8sJHm7wodtDYiqiX5TGzWxtcmDOa\ -M3GPSs4UVLO77nOFTSXN8OsIH4RfH4HYJBICieZjpi+4aAbPXdH4BFSDZeDyUOFD9eaI/XRlozk8QVW7Z/SAJyFxj650ytUh6FP8RNxqC7NuYxCG20mfneYcEUwUic3fcJ7lsoTP+E8JxbSzj/sbyrPkRIZUy3zz\ -OWhY2dIe8c4QIeLo/wQRWdKtVaMa+DX1WXNr579sF3hEToENvGew0D8q6lZvSUBV2dznidg64fQY4idcNIMmtZC1dqDGnfxiNMxLW8mbXU5KMGIxpkMLLAgi/7Fd+A6ce12AyIADFv8Cv36kKCHDR5j9gR9jrl3G\ -s0+cn4JQRY85m5SyF4Q4QwK+AMIo8LWLQ6JLgypBH8Lm8JiKZju1sqy9bO7rV3bfZFNa/0JVs3bbf4uJ4mwr4lm1wnmm/vEv0hsgQuYpbMwWR2teRJe9iC97Mb7sRXLZi7T3AhsZeqFFdIEu9NkQKu2BhUrGdYF3\ -FtjYyNXt/q4ZaGd3APgZXMBCavWckFoHtwYtyjFVSZv2rf36itD/lHzsoo/+FtPqO+5e0dEIPi/9ff/ThUcbvVy7f0a2l87ZeF+d34PvW9p9zwTVr28Tg5bBtj0iVEfC7XjQCs+xITGPXpKQ16zGgANhTwS2l4rw\ -I+l8lHxhR970B4WFnbK5E+5rqxz7Z29M0bMcY4PNt6pWu+Qc3NjCQt9Gzhf6ciaBdbOizcym2B5mJ4tzaVEBs47O9uxmqhqXctICa2QqVAan19hBLf91+K/B4Q987Co/WRz6oAf1guFLb7IjN47N6Xas2PBu8Imz\ -Mc+s71NiIKu5ZILwsLUHpmHm2OVaxFeTe4neKq5MThel21BUr50aeixsqmEsbY6GQg19IV0y1kymeBG+Fe0aJEfutzkOH0DSBn2iAI5822+fwGOPw6icD/932RAebq4+xLOO+DATSLEg66HM7hzqwaNIvf5CM4oA\ -7jF4io7Ydj8e0LGgjMUfC3v5QFNNBxn3gD1vDmD/D3g4M3jjTTjGfI7iuDVCiMeImMBNjXRKw+wRI+CWce/wmD10YA4g2iOwjbkGg/r7fEKq4hNLVEf4FReOYIyXt5Isjgack8o1xl03wJoMB39zajZTWcP9Ry9O\ -Tl7/9P4jQrKQ2hQiZOekceXeLsBnXUILcpNY7GOdVL5SILZwqqiYjRCJK7cX4DFFPotiSv+Bw9Dhze+fnGSjB3ygDA+i5blNV1EwL6ehcpHkF86hN51BwQHkRSEN0+SHvF1IhwDxXWA3EVEDCswhVH6593Do0MOb\ -Njy8acPDmza8O8QmLREWtF65xIVY5JQdwdC97yZcd/kNbhzpzvUPW3hobrBxPON7I2iTZyo6wXwI64DNLPHx+fED1ibOjRnHy84XmZOzCSkcHgwDs5TMufNGrb+2B8Jwc8dNFrvX2kzMbTuP5OTgHfc2H+iaUVcH\ -dnT5mLMqKXiS6zAqQuwSnuVonKL+hRlyII4qkOHWi+QjdpBrY/hTf8jyRM7sALzYbPydlMHyucI8AVaOsA4yn+K/7ZeTfVonD/WCWazGnZmHkWQ+EAMN5tUryFE0selSYlb84V0LzgHPTD09uiWmafj6JNxb2/Mg\ -nMoV/jtlVm12LYnxyO0TMs7tUqWWnxNCcmuRwzQWoJd8dFY0m/M47vKZuSpl11+5lwRPb/PFPnikBC/x4V1eTI3DUY9KiiuzDm2lBCnziNBYX8fcoAJXvtz7m7pqeGKXaTM8rjA63KXDgmdUeFAN58dTTqiAY4rb\ -0GFM7zIHN2yxMToYk5dLD7kSujF31kiNX9PXe+452WO88GXrERue6OT6kJ0KFMnpPYbL2Put0WAQy1kdOAlqICDdNyrYbjWTo47whJh/DYKN44ihw8O3DTp65ixu02UIRSGF83imO/yBBYOkVLJHA2SE/FE22vW3\ -R0JfIOdlZHwktyrJBzU6IWDO8QoK2DLLn9wHe90y/PIc2d9aKLQcsOWM1TkQi1dwI5BKvmfDmnHFQMGb8gEWVHQPPMKFLaRGgAw1pYx+pudV0ydv35diH+k6qYyaKwQbc/wY4nYNnnb92Bxq1msumNFS96/j1gXD\ -Xjs3IRzW4K1VbKTQ0833ALXngFq4TyN7wkdVmswIzEDQ7N5ShgeQ0BvOO4LA2lR84qeoiYKTk+nLjSdiaqBHvB1jLUT8D9+IvsZLO3T+923ohT563xvI1G1zNRN6Rnyi5JOM4QIo966UCGmgVH8S+QBT27fWgvB5\ -M7UTmOsJ5Bz9+C7zjlyHMhYTgTDJZ+i6XrsMMqycGH4xZD3oiEpsFJd8y1QQ7jJvfCqrg0zOTAm5VHSKY1dEr9a4qzJauYRtsXceFvYKrFU6IY5uEnDaANS9N2GxDknC6z3mpg9euD7Fa7dx5jaWbuO92/jYvWIw\ -6105mPfb7j1yWPmdmWvgvsVfsXlWfe3cOpjncgecsvU6Fql89w5qBsAuaDxUd6D2Wi3oXgQHVzTghXuJZ9OSGAKwr6oKH60NK8um4ZBCYX7LCUoonn/K7NKEP/HtD2v1lFxQl5GmswW/j2QzgXeX6nVXuVU1e6+U\ -ZNh5AlMdiIeR7MmnBd/x0+AqX9tQokrkLiFy+TEawuDB3B5nnR9Y6hZZTVUc/SL7gMqo4WpleYWtYG0nfs+5c20vovmJLAFuK0SsUMkXusk8XxzATPHtEzjuR54loqU39cpVc08oTkfxFINeHL3gLEhRP2GJoec/\ -wvOCtzQcaD2+mwIf0WY7Zt2hEBCiGNQjzdlXwkJRJvYztGXeVW33EGtBqhyFbSef1c41d+EaHJZmARgH8Z1odLPME678buxGUjvkfVpniXu35uQcnnsYD44CzMHEfKlbgIlFyx8PE98cfjtw09OQk4pYPZf55gGE\ -CwW6oLd5cqzKVHIjYv/iwcjxqxBM2BEhJ8m5wQT3PrKVC0hwNxMvtijMSZALuXDHLHAqdwLaYLvloBluLtxLHeUaBHB3CmqhtHRIFfP9L3VlD//mcoVkwUj/TFcB+6q+VvosZVSLIRD1o+XMoTOmi6EGb/nKLKrs\ -nrbm5L4RbhSguitA2RoXqqHLEAWI2zxE8Jjvg8zy1T4VJ38ryaMFx5CmqrBwpenqUx5lvMIrFyuMQsJKuoS1ovU4kaRQoaKWv41Q1jt4KqYT3fDn7IqUlptyOMVpDj4FEeVpcZxNPmMz3tzgE1OmMGMmzg0c3gl3\ -cGtmW+LDzqWR8qW+J3dM0sz4NaWqO0DL99W6762fZ/pQvRQ2r48GeGnxD++WxQKuLlZBGmdxmsZx+6b+ebn4xX2YtQ+rYlnIHccmR4E6ZOxsmTkbAlRwwn+IiuccEeA1rdppVKHTwBx3yg081CtvIGjkN3t8FgM7\ -hE6j0wFSKLW5Kjmm+A4bKI/Fuj5O4weasv94j9gcH0N9c41HvibfmV+Xj0je7/rPMF8lty6jwlTUWFJIRZgqnQZeBRpfOeXljZoPDq++wajboDEl/6VtfG8ocMPpCsd6DJ5xi0PIUSjzJnVHDL4c2N/ZGBpAXppf\ -U2cNKzsn/ax0/5ad3jna7glLt2KI6s46rd7V0ao3Nx4gc+1n4F6jaxudGwmLXjqnN6ZWay4IV73v+5eGh7121GvHvXbSa2e9tu62VQ8e1fl+4DY6X7o3j6vT1R2vP+1PXdEOv5CHruKpq3is306uaKdXtLNPtpef\ -aP38iVb3avJ1bf3J9uJTsnPl35fKbfJFOFp+wbr7kDdXaIEe5KoHiephUXXGG7qNG26jM2znYNu+23jmNjoEedfTND04i15b99p1tEZK1F8oxX+2Fvi9WuL3apHfq2V+rxa6qv2FfyqwyTQjgSlKHp01HbOkxWYL\ -ZcFY47yGkTR1+f8YY3Wl19nrdZ3kKA3bkDP79X8BZBZfEg==\ +eNrFPHl/2zaWX4WkHV+RE4CUKNC1G0s+ck/qpHHTXXdbEiQmnaPrKN5fMp10P/vyXSBIyXHSzmT/kE2QOB4e3o0H/HPzqnl/tbkXVZsX70tz8V6ri/dKHbZ/9MV75+B3evHeTOBt8DPy/FPbxAaFrlZbKNoHg/3c\ +4zZSMIp+Ut2Mw/LhoTw9mHED3et37PuN278TglSnF+8tvG2r1UVbbp+tiqhdDaOnF1fwroihFc/P17BUo30Bv6u2fd6+sBe/nK6H02qbNU2vabIm7y28j6K2rW1hanDCbY8loLFtU+SL9k121n4qoWY7t6aCB2hb\ +cFs1AUw8eum7fw1t5i04uAaHLRCunb6ujgBL8Mj15i/h717ewXWEf6UlDKJoEGg3beFJ91tE1AICPbRA1bjse2kfhDOpcbEJU2lfAQpyoRJfebv900H1PTQ9JcwilrvX416TDCDANdlLEO/tK18hfc7obwGwdoO/\ +pzR+XTCV1mMCRKl2WpYXSZkeGRTczsREE0AkQjgtjS2IfKBqiSVZ+MKEpCx03dx79mD2sK3bjlzi6t8zhGaNPBRyhqAp5COtBnyliEdWvTO2zzI0wqBiN8jgI4NLaPeFdvzNoMfxKnAZ5GCKxMu+k6r3pcfYZjvA\ +IHxxYQdZwNu+AELI9wZYL6kN9FCL9Bj711RHV9fLpyt5/Kb90wQFnUphPwATxvbjVyooAHmVyLj3vgoauKGQ85DBipVNIPFUCGbvIxTqYFAdCFyRVCEp9jFUSksr69WuvjFBoewKr3CVDo9P8d/oCf57/8DTzCN+\ +qsYP+cnaO/wEor5JuVCbAp9e+3cPSHbgV1juBkn58MmGgMRdtrxXMXsWIB+J97AJCe2kXEuQA2nSadmKMpuWrRSs0xLEZlqC8EvLe8QbzVREkKApJrpEwVaxgkB2BBrPQy4DkNLHybQFxAGWJrSCSjMEsDbKHu3E\ +pAYBWGw8ofVTOv6FB9d/4wFpdXZGoXZhweNhsM+pH5JeIeialsu5pBuN+4FVyqL1qC85EdCIu8uG3fH79FPfv2kXAin4jOaPKoEetDxUDJnqJDFCWa9YhgJXWp8jStY85Kxtdf52oIdZUw9VQIA/nSYzIKYEBTTA\ +YdfxzWR+dpSWyQaSFWhwm02hetuByUOpQIoRtXGK/1JgUFCVWiWRA22rt3b92FtQIymTPulomyRnR0wVaUgxoJ9L1mImO2nBmdDnBU3JDQclKeLSKBZZ0v5a0CvAUMbdIlYnxCZ+LLBFAADjeAkmtHxKg0K0oeRI\ +O3ThuoMazxirOXerpumfXKBbS27t8reRy+R9LS/BwjBuTd6j6DhlvlDuSDr/FYsveMptt4blMDyD9BJCKpagIssTmLMd6G0HmKmCHrCOk4anpE2kzyro8/S9QOjXsDeizQ0Nt9X2VlGTudSEUgvIL9StG4C6yyMC\ +Jouuie5VM4QipJ0AqoqhKsZsscHKtsbQJqz+qB3zSt4petf+DOPBdfRMVQYDroffsmBQppMJoCtYAgDawn8Hrd8QyeFK5DLSBg8rS5HJUkht/T/LwsaV1G/RzhybTXu2UDSaQcPFsOE56WmApsU4maaodEdsqXtQ\ +gcgmEZrH52tkcDdahGtOjMdjReQ0KP2XFcOBREQ9p7qPfjg3/Zqsd+N7ZMjtUlfPyS5ZAfa5+ASnf2WMWbJNbCqs7nGMVRC7UlcxtVdO1vhnWaX7S59e0ieb8xLLCEpvdNVUjp5bCjQ8jm/RTJq008AerlTojxb/\ +v1CS/wCi0kzesgTKnwaAwvKMEaI75mkr3XQd6OLm+p7Pu56tOZiX2QkQVyspr6D9PM4iXnv0naCXOrsNanYt+hORJCgjNHaJ52IWvX7sNHBKBIicTImOe9BeMQjEc1pK65cSdZOXzdxNAdIahtbmADqpWEwLEaLc\ +mXfUqKvs0KnoSMhrHew9ktST5/iP1RwwGjTSWrw6/c1RdJhG9HnaoRR1igJFFm1AtzI5DSjLAMTTcaCf0RdtPgMrNr+LWEmDKoaq6KE4bNK5eNdg7+S3O8lo0g5kFjybxMvUw1Yn4NG8JyH/DHkiFoKPBwSv8kQI\ +fuhJUVPoML6O6Xi0ptdMOj9l4FgcatQUZ8zbHn8Pur51FlLMLg3m1Bpg8vBr+IvLuArT6fOSLUOQYkDI6Xsa1leFj9PpCfQortuK+YB5TdQYLFCDXaFzu7eNts3jDL32x8diYAEqpkKTGcGA7AZoQDtq8pBmik6A\ +qId8IKKMl0OoNiedivHA5sse7yrJwyYiOHOTn9joVxRp+VEM8kt4OG8dGjtNQlvHkRXY6lPgnwmYdz52ADQzBntWTJMaOGm8kXZ1tLgP8FwE7rJdmxKGpaZF4z4VRYyjnrAdQDAwISkJrFF/MVl6SEVgkzf03Pdm\ +0N1+cNA3oGNyF10TrWFEIAG+QjnOJjlY0/2+UCzt8gpAjXxYA2RaJvErdhGavjb3cZ/m1Q8PnpqDBIc8+SsjHb5anhDbnVnS2bwoxqIsSkkgOZV0VGomj0SPcGiv+TSrPSFicRgjws6ScocJjqUvGmbjmOxx17wh\ +Gw8GqFKQG2p2REUjFJihmQYDFWm8Ax/KW4TyGsNXF5uF+HPtMNNFeasq0W4v85N9mkeVxjC0JpvVNVUMVKMeE0Lr8hh6hb5VdbUob5M1VubvuF8ky7dUKKDrSiTdgvWbochjkY6ABBbwd7L1N4QVPaFyfVFu778A\ +WvgAzDUicQHOrkOZW3mpDYQ11v8EMEmzbdEXxAWqhdiG0q4TdBC/BFaA/yYtgGoKcovKaX4PPfZ1tqmaCIsbVKyh2CLgFvSVRFswB/0fHDC1zF9oRTy0P3AEEARifsq6EKIygBeQnWP2Glo4v6UuQHXYvGB1k7Om\ +BL/Z2wi5dLDP/N6LqfkeB33RhFxNaKD51Fwqp/u7ocHMPMODFTLZFvfgpE7AVXMNTm4b0JoH8tBPbSrje4BO+8EklcUQE6GF8BFXUbIqPggQYrFSvM+vUEYSRZj0FeHcqLtoY4BEUa399bycIGmXKUQCgcCBvN8u\ +iwaiiNZCex5PkNbLNB4LG1j0nEYAXfQSUH3ebS60ZtBYmNhEE44JokE/Y+Zxop/efN0JBu0wbvUcvLrvpsH6OYyQK2I+xAKEidQCelbvIgg+fNdpCe1Oh2sVs+PRjI6KiolPiY7IwtXljy4/eMBEMeW142EVacCw\ +Mo2xEMpH64fjjbRsWcyc2hSVMEGgaLIBhWihEIlT+IG8jk26mDTRgZ/yb12kV9eHogXAZGyQQSuibrRQ2NWBQIVi9dLq4vWWpyoTxbNttgdBk2cz0h8YGarPWdDWbW0UPDDSErbEkDBLuFoSFPD44pzkjCv6BojH\ +i/kCeIF+ZVsIZ8eBy0PGAxLhB4A/ogZauBY2rvLfCGwHM6z3UYDcYvjUCix4CRJtS08W3E3H5KHGfcnjUZFfhwp1PSo+bfJOBXsvGHeqg5UHKilT2XWrIQzoPQPEj5mxfZUPId+fXYsIZp01hUwf8/5RTXoDo1X2\ +LYnhioVHhwjZIaoD+e7KOfhDGXVCiNpZJzhDPPXCiLJfBtMsk0cJVT+VRYBxxjKODcdB817GsTIOxwygx/wZW4u17hgO8Vx/ALM8IYMJPeqUn230Tl1eAiW84/gOcxM5NT30jd6edrtdFM8D8putEmCn4bQ/To37\ +GTNkk/8/MqQJGLLBPakrsYg8wfXIs/ZymjXn/hFTNhravTnHJTbY5K0F9LPiDaoxxU2NE4H9JdG0hq7NOe/ycOzOO5qWnGuE2S2NFqglgjL+Lhy+EcR5Jmn5YoTm6J/FrvtnEAZbXsIRKMRT+TxYXaEBUC9GPyUY\ +rPoV/nyzBX/fkfeiNCxN+o79ZSw5CAVNweOwuxjRQCNiAd5F345gV7MOTYkFmhBiOYAV0ZoTlySSjLp8iX8J4RhSs1M2YTwaBWHozeXeJhrMEHfiYP5lPbCo3Ib4bEKtTGzJa7CNRuxNgKfs6vlrrmxfBNNsSU4v\ +T7YshpNF1abDybbTb+fbYgDQZzjOVDBoZjw/egXTSDCEhMIf94sAI0RP6QN24agOOApUjQw+zKHAzbdXIJa/Z1zZfwSb9QgWbGQ4+FOQhNol00NX6X0iW6dj2PiqcfurFvhCnTL3oi1hj9khq73H7bOfvfRM/NBo\ +HPwuRQjuDMwTqCTUhTdLH7MUividulDkTiv9kVNn3/kZBuE1MmS5x6zr8fAZ+1uwbg2FiBRbXwJZ1rMrHqDXhtS+s65gD10lHBoVZVKBD2Z0/BgplQEnr2G1Yf+XZQIlllhl1RuRcKhEDr7CdVu/SW93Ji/03GTn\ +czL+zcCCWXaB/oXWy2nPdEEczjh0N6TJFttqfec4vjswbupOd3ubl/Aec/ypBqNXZ9N75MJrm0FcWGcoIk9lQ1k96UIJuKlr9fG1AnO+UoDg9o4mk9xZnC6nYWH+Sjpjc6He2Wam7gZjE6JIaS9zb3mAltvAhtNG\ +iAiTtq7vSqHz0utki8Kh0FNS7nLopyVX3gUtMJMhKe887UitlYN9alM9+oCB3auO0jX1mCbCAIRrncZ3Du8CKFMxTdDPArmht3FDtRwF4Qx1RO0xyq2PH4FqmZdbbA64eTxChMOL8njn7hwaO9nMNSWSAARVafMj\ +A3NPkxJ1FhKcjJ0n0IfLk1HMMTaOdtjiFS/mDoSsYDo5ehXiobMuqCSMmu3cTcs9XLoRWIZZgrvQ+ZMlzlsyJUbgY8KesbMFisD/9dEunKBkz7RqDJk15xRBDakIFB5CPQKYgRUo2mXF2EIdbDu2CiAuPHowuW+M\ +Q2wlpYnWI/wKQBbF4WyG89ial8U5R7lZpUC/Zlo8xpZ7lw+YYtQxRkOPqWs9RzjbGqrzmFECmEOuVrIVjbv0eoeigjQDU8N8C0nAsJy0ZOh/uIlYEK+1q3T3EarGV/79FpGxwaUq77KWzSRzrjKdZYz7CbCukBxU\ +QJQDkyUsxQCNpMcoijhSr4cC0JyYWuF+bY0A2KcUG6WoahNtzzoLJ/SqCknS4qxLg7HM3YurD+RG4zscAUWOCuDRLGDsow4xnwqPF1GobQ1TVQQ9zhL6YAlBhs0EzGbAcPc4OgYYEcDDh0hZCNqjZ61EJhw7C3UK\ +lcR7ybfQ1zzewyEh4FkdixE0L/EtMGy7Wnfa2kjZRRfGp8ShNN7dWJOd8iBfIcwtgJ2KmvM0KFIr8SO1Q2KvzBP5tCEJMRmtcaNo1cFdsztrELsvkEW8q5hiaDvSlG+JLqRS22Al2ucXmwdi3d8Sj7MKUssyhizb\ +4kUNDIdLQDm4iS1at1tIN99QFA6gQiRlvyYeHAnA1rz7hIFnKzukykRg8de00/BRtb8ieoM7QeAvwvoV6gvr/nANZWemLrvNnmG+kN8yMdVBz25DM9oPf/uasdciGV5MB63ipkcLb2ZEC5eI/DSkhaxHC4ZoodDQ\ +p5GwD8Nb6B+oVySE8QfSG7oSvI6RCCBHj4VxtKV21kHAJJf9VX9KEq8ArPt9mL7x6U3TpNyQ7baLTdiNGse7otTAOYYA0LOOxigZrBDLSeU5+XwboC+nJLhr3rtBMiF5sXE6NNIHNKZZg6v8PzHv7JQw6neHvD2X\ +lByD/Frotp8XeJOroe0aBzpMF+75FD/jIxS7iNeXCaejl5bZkILeHfBudRqv6zREMm1D9VTeO+qjAImgqnd+zw0XEA3wxSCabXoLvPMONqccZx/TWu/cFdMDVqu4WDDWcNOvPMLMJWdJvaTSO8YCrjVoC2o9dP9/\ +xXTDvsMx3PiQ0Bj8qjmIFr2Av+mvV+/87v27Lquu4DiPza+JCGj7AkTR2nLCNoyBm7c25rw9e4Cm6uppkfePyXr9yZG7H3PsqUoRaAQ93eOcVjTUB41WRAdkj7faYqlcJdu8xPAJpDprWzC82Y6rOa5VpV3ky2D2\ +EEZi9nhUlo4l5vk1M3bdq2/GotvWRAX9SfTjOr3plOLpXeaLrvIGx03Ruqtw8wCEX08BVisUoFutAO2yAlSrFOHGJyjChdgVKxQgaUZCHoWNb7/F2IwowBIFCdoxH5MkK7TgW0oz1pKKSfHF67Xh5EtoQ86Q+LIK\ +EYisuoks0I8Ad0iJOiRDelsC5GpZKRItoC5cdHatrtZ6BEEqjU1j7Mpw7qLLUBQdctq6InLEELtlQiwgMcqryf7eT+TVZJfP4qacOIyoPukSSENpjKlSHByu7fDERz8sfYKIk7gw7gt0gehT2h/qm67AYELfSgc0\ +I0kaa9F1dMOr2i1d4Krw0s0gD7TaS1aYtrSESuOa1XnWZXeXeLpp/QMHCVcaLGqq9sazvxCdtJrtMGN7CXPU0GxJ2WiWSE4doPWapSG/Q2VhKhkoR/RhG0AX2CVwCmEFutABxdT869gM7A/Lm7sd1uZLWHsDAdnq\ +Edti8xBr5OVG+vAhJ+4Q+RCMvwDe7vMUp0P5tmgFP+I0uthsdSsEFzbfPBEMDg2/39hHB1vf1UJFwWII8g4HyEuJ43DjA3GeDuLJLVKgN30bMlNzPjrhAFIzZp7wfthEcIgB1dYQcSIZ3gEifk04MX89rlnNtQbR\ +r4tEDjVpTCLMCbSqPhaQws3m02t2msXeW4OTB3g6hZWJ5t0aNBRYUH9CtsbSFld67RYXRNjd0BTMyIwjWa28GViVNOsudBWYftxGVRjRyvik1TCY3Df35PRd4/WmLIh3bfcG6t+SRn/DocHKuzOXwpbAhQqPVWR9\ +UhYBjru1Csm6st/e/zTNPmYIx6jZ3YA+DSd++KOmY3VP7eHBNTaKMGAFNmqZXfYFCCv5jFNWzfgpBIaIilglLhESr+30U2nJMC0BTVl2GMDe8zRU/GEaWiYgtUrl40pnQQokZ80bP5/59aoeI2rp9aqehh1HaknV\ +k9WO6celJxnWPJ9GNUaoRq1Q+K35u6B1RmKZsvX3ERGpCrUHW3m4b6f6FOEF4lqg4q8RhTNONa+E6/TeMe7RzMv1GR+Crlr+3hsbjI+B46xZSqkcrcn5Z1KY8RRmlimsYvOhyv4NFFakNwsqcLlAVoF/688fcKNp\ +rxFvo3fyisOL/kjptIfyy0D7ULajZreiXEBPuPMx8c7ybc4lceVlwS9plEcZRp238eTClDWPxujHm/+G+jvH96f3T0XAxnzmshy9KKpTPFmx/yImxAItK7teIBZ/vN5Wc1hVbDWMd8bbCDQAegk+HGWPUpeU56ow\ +kCHqFOVXkZxI6LncRsUrrI9nT/j8jPcm7GAHAPNeWWv4ZPWa+pRPmjS2FNOvMnyRfvUSQtn3SIKUHM/WvhkpeuXAAZwM+oJJveTwtoSY0+5Ylmh/18j2OoTn0aGc8mlTVA8/E0F3+WTz1flkJr9By3NUZ0RQii9m\ +8tccSFuVxpJ/qTSW+nfnlZG+Ql/mk1LLBjuzI85LYXTYHPIH7Kpg15dILJOM/zBth3N5AgvhhoyBgfM9Iv3bLfjhv3KG+hkxL8U7H/BY3lXY5n0hTPSCFKtaclwHsuIhypo1yQJVYx8E7dUDDTeOj2lMiAeiDdnO\ +eBt0+oL0n8Pc5YoCrLD11aSLitUxvobjFbXtEnIU86dFOeokLf0Uj5Hrn9k7NrAueKpgXmY+B17OApaDs4BMum78A6fp8EvI9zdslij7jzkGubp9Xz4SVPosCj4EAD+wI+DnP7JtUfIPkzL4qJM/5ZTx96kcoudy\ +WGf8kW+Tj3zLP/JtMB7A1nDZVMkezOI7tLK/WZsB9hNaAryOAG9ZycP8bq8OoGXX184es3/6HehTB3kirsRzSEE+N4UoaddfluxsuGRg27gS8/Yx7HI3Yv3Yr4bpWl0e0zccd+TUgTPMAm0XdB5nnXlj7OtdIuJK\ +Fd0hrCbr2B639bUc4ON1hgyvpuCdcybT2n5LpFgyTTUNbxo2nAaIG+jZkksaBJNtZxg7ubsFUkr1bR6bzMpyq1XWOyCUYWcBdUuzDXkEFSQZYNARnFSrgjzpMrobQfyxWZQ70V0inxoGMHSWkFPbYEukztjmAcE0\ +ObzFMSCJ20i4vWyXcPdicYKRCmQVvOCkkeMqcKsJ+hUFNy629vm2CcTQXS2nb8AppIAH2y1gvdb+mK4cc5xuX1xAhT0+LIuBtwY65dNhDzkZRE4Fdocg5GXBXZwgFnfDyCeKrrgDGcPg2bL8wPdm+b0BYwRfwuFL\ +K6eZ8wMBqjvVtFhuLSFvisLtsSmnOc7fqxxxNJ3DAHg2QQ7YwmlRB+M7NYogwgn7bv7snGF3x7Ix5iqUmlkiZ7YmIwmghucpLJ/dJNpFL/v9b6//ToevtnY72kXTKif0hZNr6vD+BGIGm3aRDLQRKm6vltv7/vm0\ +GE13a9ccrLqhAU/21f6oIedSxXw/U/HgB7P7UI6vAYMVRSc0EXq4fAJkF1IBqjy+mqM7caoos9pABksFiq046MDU9qGcUUx9xSA7rxxEuZWcccvxgDFSNJhPwG2OD6MpmXYaH/UvLrFpjFeTxHg1CR7DSeN7FMfX\ +OrxUSClJKJbLs1RQUEsFH6OJeXPN9c//KbV+fsSpZqjd4bIOV/YqIm41hdaC1w9712vgzSLnV70aWwHJZBFmYahEDadjlu4wOuxuD+qiMuGcg4u6bFryKmjOQUBwS+SJETXUeNQNz7ryzDClmhUp7qDg2eaJ4AAq\ +SAIeKRJNwe8hVvrIPMerSMwT5kw5rQpZc7i/CPuGeNdEZUbfcDTNWkj3E+VNl0SYUclbbO7wRe8eMhgm92umyax0Dghbw1niZrIEI27wqU9bOfMkwvfFEzPaWdseye1XQD2rLrl6Inf9yEeUCkC1Vv/IyMRsH7MP\ +umN2cfUGNMxZJ06cRAh1F2LXfDcYamRDSIGQWe1oJrWdDXfIWHRO+Bya23rCDiUaYFsjcEdKPucARCIZtjrnPUm3xcfY1DOwUtTXfB1Od1VbQLBWMujsuNVF2PLBPqsIpzDPaBtFCJzgNG8AgQC+OeNzA874S8Mi\ +QWZ4VZZSZyccbOoo/UqOmY3n6BarJ7OHtzyzQt3J9gT3eMePkp21aDTbPpEkxaSRizXerpDMRotMnERrJNFX32hGP/XVYNEROH9mnDOvtFwwU4tSqIaYlAqhu9Q7N0nN5Yy0CZTTyn5qrjBecVOR0R+f1ECoFLG/\ +AvCK7yVS6R6I6J7pFzhsfnOG79ARSQMBZn+cKGUb1OJDetMNckq9Ck+TXvaPlmKyrfEXaz3Gp3HwDoM6hVynFSzBErcCayKnev7srtISXk3IbNRyuFGYdrLiqhYxuwpRiJKAjsl9Uznhwe/c04sFqF7NVxx4E2LY\ +rU2fAnq00lEADbJpvVy9ZseoZrvYKjja7+pYxGTa9UG3LYmxO7yBqkkD6Zxh7ROZ+W5n1izl/pd4kEIO5Duvzz9ZKPTpsrvG6YpTvqvqd5D665CMrsLC+7DwoU9tZnDbYDEsdxfE1V+FNFcPaa7kCKtj4kN6E+JD\ +SgyJT5dum4/SOl6Gur9w3jzBU24jvhYMd0UCK5hcvOeeW/9Om2+raU2OIJruFi3a27hPgWu+G6IqV90al8vVnGgu7ZzBQMfMRfZ7uVPmq+GdoHKdaM2xtzIzRG2NWpOLNOSglEikM9naPGBHo3wJNtfkjDjL4fEp\ +i+/lih9/u9zgxjjZs2nHfd0FMf0dK2nyd9KWtu4sbTpsOeMsIeiRWa6d8M8s0yeybv4QFwvIhsU02myaWAkSQ9WTiFicqhZuCOwZZ3ggsC9fsVlf3jojIuT3QDSTmHxIepVUCc/VZn6uiOMpXSdYwqohq7mf7gj1\ +0cbLfZ+NFATZ8u7eQOxVr4C0snKqAI+bpbf420T2YWhZG07VdJhzD7qjGktDR8xny5wuZO3Cn/6GCwcRiowVZZ1uPLnYjKkV4H0RyDezpBxP5O7Y+MOSlKOVkgmbicjHUXBln+HziD03WqLdMRm8zlW7xG9tp+QV\ +bBKn2PLPXwe5QjVfaxIGbTGdfvx7BCgGB+ciNWHc7D7fpQeumg3c2e5mh+Bgh8rwvgvqTI7yTTcSin2apcT4uZgseFYRh7qNseJtucTWLNk+eNpggjoSQcGqeI9WX3JL33h0N5VpVL1mncW1EH1B3NPraXMU4aXN\ +P769KhdwdbNW07EZT6fjcful+eVq8Y/wpWlf1uVVyXc8925uxUWeBNab5GoKJjP+yWV7Kac24P2gJiiI7sWCrYKCCOG2sMVbjvB66oIC3KXiC0ED3hwrsbBHR12pTh0Wwga9AggfuK1gRb8VxQSxIPdM+Gn5wnVd\ +l2wkDV7/J5/EVnzExaGTePg9X9ksN6i6iTTVYeHaaVxXiK6r0/QKfIWUFpXOS/OabHFaAOfRfMc/kQ/LhXdBj6LMfifYv6fwKoAKHBxfMCqYxtLVycMgbzYoD72W4TXn0175qldaDPyPwdjhTVF0+1yornv3B3SF\ +cvnS5p6DrFdcFa0H9fXgezooZ4PyeFDOB2UzKNtBHHZFXLYrR2GhVzO8n1r/tCIY/+/66RvK6WfS0E00dRONDcv5DeXpDWXz0fLVR0q/fKS0nIG1IiPrI+XFx3jnxt/n8m3+WTi6+ox5DyF3N0iBAeR6AMnw4nLd\ +628tLNwOC71ue77IUVh4ERZ6C/J2IGkGcJaDsh2Um2wFl+gvyMX/binwR6XEH5Uif1TK/FEpdFP5M39adYEyz4FT5LzuasgqPP8uF/xJRMlz2iodd+1MN9n6DY3lbJqq1jb+7f8APK6wwQ==\ """))) ESP32ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -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\ """))) diff --git a/tools/get.py b/tools/get.py index 31ea0ad978f..cb1cfb95cb9 100755 --- a/tools/get.py +++ b/tools/get.py @@ -25,10 +25,12 @@ if sys.version_info[0] == 3: from urllib.request import urlretrieve + from urllib.request import urlopen unicode = lambda s: str(s) else: # Not Python 3 - today, it is most likely to be Python 2 from urllib import urlretrieve + from urllib import urlopen if 'Windows' in platform.system(): import requests @@ -58,7 +60,7 @@ def report_progress(count, blockSize, totalSize): def unpack(filename, destination): dirname = '' - print('Extracting {0}'.format(os.path.basename(filename))) + print('Extracting {0} ...'.format(os.path.basename(filename))) sys.stdout.flush() if filename.endswith('tar.gz'): tfile = tarfile.open(filename, 'r:gz') @@ -74,19 +76,38 @@ def unpack(filename, destination): # a little trick to rename tool directories so they don't contain version number rename_to = re.match(r'^([a-z][^\-]*\-*)+', dirname).group(0).strip('-') if rename_to != dirname: - print('Renaming {0} to {1}'.format(dirname, rename_to)) + print('Renaming {0} to {1} ...'.format(dirname, rename_to)) if os.path.isdir(rename_to): shutil.rmtree(rename_to) shutil.move(dirname, rename_to) +def download_file(url,filename): + import ssl + import contextlib + ctx = ssl.create_default_context() + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + with contextlib.closing(urlopen(url,context=ctx)) as fp: + block_size = 1024 * 8 + block = fp.read(block_size) + if block: + with open(filename,'wb') as out_file: + out_file.write(block) + while True: + block = fp.read(block_size) + if not block: + break + out_file.write(block) + else: + raise Exception ('nonexisting file or connection error') + def get_tool(tool): sys_name = platform.system() archive_name = tool['archiveFileName'] local_path = dist_dir + archive_name url = tool['url'] - #real_hash = tool['checksum'].split(':')[1] if not os.path.isfile(local_path): - print('Downloading ' + archive_name) + print('Downloading ' + archive_name + ' ...') sys.stdout.flush() if 'CYGWIN_NT' in sys_name: import ssl @@ -100,16 +121,16 @@ def get_tool(tool): f.write(r.content) f.close() else: - urlretrieve(url, local_path, report_progress) - sys.stdout.write("\rDone\n") - sys.stdout.flush() + is_ci = os.environ.get('GITHUB_WORKSPACE'); + if is_ci: + download_file(url, local_path) + else: + urlretrieve(url, local_path, report_progress) + sys.stdout.write("\rDone\n") + sys.stdout.flush() else: print('Tool {0} already downloaded'.format(archive_name)) sys.stdout.flush() - #local_hash = sha256sum(local_path) - #if local_hash != real_hash: - # print('Hash mismatch for {0}, delete the file and try again'.format(local_path)) - # raise RuntimeError() unpack(local_path, '.') def load_tools_list(filename, platform): @@ -132,11 +153,11 @@ def identify_platform(): bits = 64 sys_name = platform.system() sys_platform = platform.platform() - print('System: %s, Info: %s' % (sys_name, sys_platform)) - if 'Linux' in sys_name and sys_platform.find('arm') > 0: + if 'Linux' in sys_name and (sys_platform.find('arm') > 0 or sys_platform.find('aarch64') > 0): sys_name = 'LinuxARM' if 'CYGWIN_NT' in sys_name: sys_name = 'Windows' + print('System: %s, Bits: %d, Info: %s' % (sys_name, bits, sys_platform)) return arduino_platform_names[sys_name][bits] if __name__ == '__main__': @@ -146,4 +167,4 @@ def identify_platform(): mkdir_p(dist_dir) for tool in tools_to_download: get_tool(tool) - print('Done') + print('Platform Tools Installed') diff --git a/tools/platformio-build.py b/tools/platformio-build.py index e3b68683433..93c021a2bfb 100644 --- a/tools/platformio-build.py +++ b/tools/platformio-build.py @@ -165,7 +165,7 @@ ], LIBS=[ - "-lgcc", "-lopenssl", "-lbtdm_app", "-lfatfs", "-lwps", "-lcoexist", "-lwear_levelling", "-lesp_http_client", "-lprotobuf-c", "-lhal", "-lnewlib", "-ldriver", "-lbootloader_support", "-lpp", "-lfreemodbus", "-lmesh", "-lsmartconfig", "-ljsmn", "-lwpa", "-lethernet", "-lphy", "-lapp_trace", "-lconsole", "-lulp", "-lwpa_supplicant", "-lfreertos", "-lbt", "-lmicro-ecc", "-lesp32-camera", "-lcxx", "-lxtensa-debug-module", "-ltcp_transport", "-lmdns", "-lvfs", "-lesp_ringbuf", "-lsoc", "-lcore", "-lfb_gfx", "-lsdmmc", "-llibsodium", "-lcoap", "-ltcpip_adapter", "-lprotocomm", "-lesp_event", "-limage_util", "-lc_nano", "-lesp-tls", "-lasio", "-lrtc", "-lspi_flash", "-lwpa2", "-lwifi_provisioning", "-lesp32", "-lface_recognition", "-lapp_update", "-lnghttp", "-lspiffs", "-lface_detection", "-lespnow", "-lnvs_flash", "-lesp_adc_cal", "-llog", "-ldl_lib", "-lsmartconfig_ack", "-lexpat", "-lm", "-lfr", "-lmqtt", "-lc", "-lheap", "-lmbedtls", "-llwip", "-lnet80211", "-lesp_http_server", "-lpthread", "-ljson", "-lesp_https_ota", "-lfd", "-lstdc++" + "-lgcc", "-lesp32", "-lphy", "-lesp_http_client", "-lmbedtls", "-lrtc", "-lesp_http_server", "-lbtdm_app", "-lspiffs", "-lbootloader_support", "-lmdns", "-lnvs_flash", "-lfatfs", "-lpp", "-lnet80211", "-ljsmn", "-lface_detection", "-llibsodium", "-lvfs", "-ldl_lib", "-llog", "-lfreertos", "-lcxx", "-lsmartconfig_ack", "-lxtensa-debug-module", "-lheap", "-ltcpip_adapter", "-lmqtt", "-lulp", "-lfd", "-lfb_gfx", "-lnghttp", "-lprotocomm", "-lsmartconfig", "-lm", "-lethernet", "-limage_util", "-lc_nano", "-lsoc", "-ltcp_transport", "-lc", "-lmicro-ecc", "-lface_recognition", "-ljson", "-lwpa_supplicant", "-lmesh", "-lesp_https_ota", "-lwpa2", "-lexpat", "-llwip", "-lwear_levelling", "-lapp_update", "-ldriver", "-lbt", "-lespnow", "-lcoap", "-lasio", "-lnewlib", "-lconsole", "-lapp_trace", "-lesp32-camera", "-lhal", "-lprotobuf-c", "-lsdmmc", "-lcore", "-lpthread", "-lcoexist", "-lfreemodbus", "-lspi_flash", "-lesp-tls", "-lwpa", "-lwifi_provisioning", "-lwps", "-lesp_adc_cal", "-lesp_event", "-lopenssl", "-lesp_ringbuf", "-lfr", "-lstdc++" ], LIBSOURCE_DIRS=[ diff --git a/tools/sdk/bin/bootloader_dio_40m.bin b/tools/sdk/bin/bootloader_dio_40m.bin index 70d4510a14d..ac057886d98 100644 Binary files a/tools/sdk/bin/bootloader_dio_40m.bin and b/tools/sdk/bin/bootloader_dio_40m.bin differ diff --git a/tools/sdk/bin/bootloader_dio_80m.bin b/tools/sdk/bin/bootloader_dio_80m.bin index 4b77aab0622..726e1ca9145 100644 Binary files a/tools/sdk/bin/bootloader_dio_80m.bin and b/tools/sdk/bin/bootloader_dio_80m.bin differ diff --git a/tools/sdk/bin/bootloader_dout_40m.bin b/tools/sdk/bin/bootloader_dout_40m.bin index 464a0b1ab5a..eab1e96d1f5 100644 Binary files a/tools/sdk/bin/bootloader_dout_40m.bin and b/tools/sdk/bin/bootloader_dout_40m.bin differ diff --git a/tools/sdk/bin/bootloader_dout_80m.bin b/tools/sdk/bin/bootloader_dout_80m.bin index b66faeee2b3..4d1f69f44c1 100644 Binary files a/tools/sdk/bin/bootloader_dout_80m.bin and b/tools/sdk/bin/bootloader_dout_80m.bin differ diff --git a/tools/sdk/bin/bootloader_qio_40m.bin b/tools/sdk/bin/bootloader_qio_40m.bin index 70d4510a14d..0c2e9fe279a 100644 Binary files a/tools/sdk/bin/bootloader_qio_40m.bin and b/tools/sdk/bin/bootloader_qio_40m.bin differ diff --git a/tools/sdk/bin/bootloader_qio_80m.bin b/tools/sdk/bin/bootloader_qio_80m.bin index 627d104cc2c..944f4947edf 100644 Binary files a/tools/sdk/bin/bootloader_qio_80m.bin and b/tools/sdk/bin/bootloader_qio_80m.bin differ diff --git a/tools/sdk/bin/bootloader_qout_40m.bin b/tools/sdk/bin/bootloader_qout_40m.bin index 898b8e0c9d4..07a6be715c0 100644 Binary files a/tools/sdk/bin/bootloader_qout_40m.bin and b/tools/sdk/bin/bootloader_qout_40m.bin differ diff --git a/tools/sdk/bin/bootloader_qout_80m.bin b/tools/sdk/bin/bootloader_qout_80m.bin index a514b2ed660..8cfb0c2529e 100644 Binary files a/tools/sdk/bin/bootloader_qout_80m.bin and b/tools/sdk/bin/bootloader_qout_80m.bin differ diff --git a/tools/sdk/include/bootloader_support/bootloader_common.h b/tools/sdk/include/bootloader_support/bootloader_common.h index 194d2769cbd..e884856f6d2 100644 --- a/tools/sdk/include/bootloader_support/bootloader_common.h +++ b/tools/sdk/include/bootloader_support/bootloader_common.h @@ -14,6 +14,7 @@ #pragma once #include "esp_flash_data_types.h" +#include "esp_image_format.h" /// Type of hold a GPIO in low state typedef enum { @@ -92,6 +93,17 @@ bool bootloader_common_label_search(const char *list, char *label); */ esp_err_t bootloader_common_get_sha256_of_partition(uint32_t address, uint32_t size, int type, uint8_t *out_sha_256); +/** + * @brief Check if the image (bootloader and application) has valid chip ID and revision + * + * @param img_hdr: image header + * @return + * - ESP_OK: image and chip are matched well + * - ESP_FAIL: image doesn't match to the chip + */ +esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr); + + /** * @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode. */ diff --git a/tools/sdk/include/bootloader_support/esp_efuse.h b/tools/sdk/include/bootloader_support/esp_efuse.h index c094a6ab445..047a971a4c1 100644 --- a/tools/sdk/include/bootloader_support/esp_efuse.h +++ b/tools/sdk/include/bootloader_support/esp_efuse.h @@ -91,6 +91,13 @@ esp_err_t esp_efuse_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_wor */ void esp_efuse_write_random_key(uint32_t blk_wdata0_reg); +/** + * @brief Returns chip version from efuse + * + * @return chip version + */ +uint8_t esp_efuse_get_chip_ver(void); + #ifdef __cplusplus } #endif diff --git a/tools/sdk/include/bootloader_support/esp_image_format.h b/tools/sdk/include/bootloader_support/esp_image_format.h index bce3b1d7fad..0e2bb5283dd 100644 --- a/tools/sdk/include/bootloader_support/esp_image_format.h +++ b/tools/sdk/include/bootloader_support/esp_image_format.h @@ -55,6 +55,19 @@ typedef enum { #define ESP_IMAGE_HEADER_MAGIC 0xE9 +/** + * @brief ESP chip ID + * + */ +typedef enum { + ESP_CHIP_ID_ESP32 = 0x0000, /*!< chip ID: ESP32 */ + ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */ +} __attribute__((packed)) esp_chip_id_t; + +/** @cond */ +_Static_assert(sizeof(esp_chip_id_t) == 2, "esp_chip_id_t should be 16 bit"); + + /* Main header of binary image */ typedef struct { uint8_t magic; @@ -71,8 +84,12 @@ typedef struct { uint8_t wp_pin; /* Drive settings for the SPI flash pins (read by ROM bootloader) */ uint8_t spi_pin_drv[3]; - /* Reserved bytes in ESP32 additional header space, currently unused */ - uint8_t reserved[11]; + /*!< Chip identification number */ + esp_chip_id_t chip_id; + /*!< Minimum chip revision supported by image */ + uint8_t min_chip_rev; + /*!< Reserved bytes in additional header space, currently unused */ + uint8_t reserved[8]; /* If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum. Included in image length. This digest * is separate to secure boot and only used for detecting corruption. For secure boot signed images, the signature * is appended after this (and the simple hash is included in the signed data). */ diff --git a/tools/sdk/include/config/sdkconfig.h b/tools/sdk/include/config/sdkconfig.h index 6d6152bce40..444fb1a682a 100644 --- a/tools/sdk/include/config/sdkconfig.h +++ b/tools/sdk/include/config/sdkconfig.h @@ -75,6 +75,7 @@ #define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 #define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 #define CONFIG_CAMERA_CORE1 1 +#define CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL 5 #define CONFIG_MB_SERIAL_BUF_SIZE 256 #define CONFIG_CONSOLE_UART_BAUDRATE 115200 #define CONFIG_SPIRAM_SUPPORT 1 @@ -153,8 +154,10 @@ #define CONFIG_ADC2_DISABLE_DAC 1 #define CONFIG_HFP_ENABLE 1 #define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM 100 +#define CONFIG_ESP32_REV_MIN_0 1 #define CONFIG_LOG_DEFAULT_LEVEL 1 #define CONFIG_TIMER_QUEUE_LENGTH 10 +#define CONFIG_ESP32_REV_MIN 0 #define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT 1 #define CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE 0 #define CONFIG_MAKE_WARN_UNDEFINED_VARIABLES 1 @@ -295,6 +298,7 @@ #define CONFIG_REDUCE_PHY_TX_POWER 1 #define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 #define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 #define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" #define CONFIG_MBEDTLS_HAVE_TIME 1 #define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 @@ -336,6 +340,7 @@ #define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 #define CONFIG_SPIFFS_PAGE_SIZE 256 #define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_ESP32_DPORT_WORKAROUND 1 #define CONFIG_PPP_MSCHAP_SUPPORT 1 #define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 #define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT 2048 @@ -355,3 +360,5 @@ #define CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR 1 #define CONFIG_ESP32_WIFI_IRAM_OPT 1 #define CONFIG_FATFS_API_ENCODING_ANSI_OEM 1 +#define CONFIG_ARDUINO_IDF_COMMIT "d3e562907" +#define CONFIG_ARDUINO_IDF_BRANCH "release/v3.2" diff --git a/tools/sdk/include/esp-face/dl_lib_matrix3d.h b/tools/sdk/include/esp-face/dl_lib_matrix3d.h index 82e671f8ded..4de26b4209a 100644 --- a/tools/sdk/include/esp-face/dl_lib_matrix3d.h +++ b/tools/sdk/include/esp-face/dl_lib_matrix3d.h @@ -27,24 +27,22 @@ typedef enum */ typedef struct { - /******* fix start *******/ - int w; // Width - int h; // Height - int c; // Channel - int n; // Number, to record filter's out_channels. input and output must be 1 - int stride; - fptp_t *item; - /******* fix end *******/ + int w; /*!< Width */ + int h; /*!< Height */ + int c; /*!< Channel */ + int n; /*!< Number of filter, input and output must be 1 */ + int stride; /*!< Step between lines */ + fptp_t *item; /*!< Data */ } dl_matrix3d_t; typedef struct { - int w; // Width - int h; // Height - int c; // Channel - int n; // Number, to record filter's out_channels. input and output must be 1 - int stride; - uc_t *item; + int w; /*!< Width */ + int h; /*!< Height */ + int c; /*!< Channel */ + int n; /*!< Number of filter, input and output must be 1 */ + int stride; /*!< Step between lines */ + uc_t *item; /*!< Data */ } dl_matrix3du_t; typedef struct diff --git a/tools/sdk/include/esp-face/dl_lib_matrix3dq.h b/tools/sdk/include/esp-face/dl_lib_matrix3dq.h index 31da2c05747..57e5e92c22e 100644 --- a/tools/sdk/include/esp-face/dl_lib_matrix3dq.h +++ b/tools/sdk/include/esp-face/dl_lib_matrix3dq.h @@ -3,20 +3,21 @@ typedef int16_t qtp_t; -/* - * Matrix for 3d - * @Warning: the sequence of variables is fixed, cannot be modified, otherwise there will be errors in esp_dsp_dot_float +/** + * Matrix for input, filter, and output + * @Warning: the sequence of variables is fixed, cannot be modified, otherwise there will be errors in + * some handwrite xtensa instruction functions */ typedef struct { /******* fix start *******/ - int w; // Width - int h; // Height - int c; // Channel - int n; // Number, to record filter's out_channels. input and output must be 1 - int stride; - int exponent; - qtp_t *item; + int w; /*!< Width */ + int h; /*!< Height */ + int c; /*!< Channel */ + int n; /*!< Number of filter, input and output must be 1 */ + int stride; /*!< Step between lines */ + int exponent; /*!< Exponent for quantization */ + qtp_t *item; /*!< Data */ /******* fix end *******/ } dl_matrix3dq_t; @@ -32,21 +33,28 @@ typedef struct #define DL_SHIFT_AUTO 32 #endif +/** + * Implementation of matrix relative operations + */ typedef enum { - DL_C_IMPL = 0, - DL_XTENSA_IMPL = 1 + DL_C_IMPL = 0, /*!< ANSI C */ + DL_XTENSA_IMPL = 1 /*!< Handwrite xtensa instruction */ } dl_conv_mode; + +/** + * Configuration of mobilenet operation + */ typedef struct { - int stride_x; - int stride_y; - dl_padding_type padding; - dl_conv_mode mode; - int dilate_exponent; - int depthwise_exponent; - int compress_exponent; + int stride_x; /*!< Strides of width */ + int stride_y; /*!< Strides of height */ + dl_padding_type padding; /*!< Padding type */ + dl_conv_mode mode; /*!< Implementation mode */ + int dilate_exponent; /*!< Exponent of dilation filter */ + int depthwise_exponent; /*!< Exponent of depthwise filter */ + int compress_exponent; /*!< Exponent of compress filter */ } dl_matrix3dq_mobilenet_config_t; // @@ -54,75 +62,166 @@ typedef struct // /* - * @brief Allocate a 3D matrix + * @brief Allocate a 3d quantised matrix * - * @param n,w,h,c number, width, height, channel - * @return 3d matrix + * @param n Number of filters, for input and output, should be 1 + * @param w Width of matrix + * @param h Height of matrix + * @param c Channel of matrix + * @param e Exponent of matrix data + * @return 3d quantized matrix */ dl_matrix3dq_t *dl_matrix3dq_alloc(int n, int w, int h, int c, int e); /* - * @brief Free a 3D matrix + * @brief Free a 3d quantized matrix * - * @param m matrix + * @param m 3d quantised matrix */ void dl_matrix3dq_free(dl_matrix3dq_t *m); -/** - * @brief Zero out the matrix - * Sets all entries in the matrix to 0. - * - * @param m Matrix to zero - */ - /** * @brief Copy a range of items from an existing matrix to a preallocated matrix * - * @param in Old matrix (with foreign data) to re-use. Passing NULL will allocate a new matrix. + * @param dst The resulting slice matrix + * @param src Old matrix to slice. * @param x X-offset of the origin of the returned matrix within the sliced matrix * @param y Y-offset of the origin of the returned matrix within the sliced matrix * @param w Width of the resulting matrix * @param h Height of the resulting matrix - * @return The resulting slice matrix */ void dl_matrix3dq_slice_copy(dl_matrix3dq_t *dst, dl_matrix3dq_t *src, int x, int y, int w, int h); +/** + * @brief Transform a fixed point matrix to a float point matrix + * + * @param m Quantized matrix + * @return Float point matrix + */ dl_matrix3d_t *dl_matrix3d_from_matrixq(dl_matrix3dq_t *m); +/** + * @brief Transform a float point matrix to a fixed point matrix with pre-defined exponent + * + * @param m Float point matrix + * @param exponent Exponent for resulting matrix + * @return Fixed point matrix + */ dl_matrix3dq_t *dl_matrixq_from_matrix3d_qmf(dl_matrix3d_t *m, int exponent); +/** + * @brief Transform a float point matrix to a fixed point matrix. The exponent is defined by the distribution of the input matrix. + * + * @param m Float point matrix + * @return Fixed point matrix + */ dl_matrix3dq_t *dl_matrixq_from_matrix3d(dl_matrix3d_t *m); qtp_t dl_matrix3dq_quant_range_exceeded_checking(int64_t value, char *location); +/** + * @brief Reform a quantized matrix with exponent + * + * @param out Preallocated resulting matrix + * @param in Input matrix + * @param exponent Exponent for resulting matrix + */ void dl_matrix3dq_shift_exponent(dl_matrix3dq_t *out, dl_matrix3dq_t *in, int exponent); +/** + * @brief Do batch normalization for a quantized matrix + * + * @param m Input and output quantized matrix, data will be updated + * @param scale Scale of batch-norm + * @param offset Offset of batch-norm + */ void dl_matrix3dq_batch_normalize(dl_matrix3dq_t *m, dl_matrix3dq_t *scale, dl_matrix3dq_t *offset); +/** + * @brief Add two quantized matrix with a pre-defined exponent + * + * @param in_1 Adder 1 + * @param in_2 Adder 2 + * @param exponent Exponent for resulting matrix + * @return Result of accumulation of two matrix + */ dl_matrix3dq_t *dl_matrix3dq_add(dl_matrix3dq_t *in_1, dl_matrix3dq_t *in_2, int exponent); // // Activation // +/** + * @brief Do relu for a quantized matrix + * + * @param in Input and output quantized matrix, data will be updated + */ void dl_matrix3dq_relu(dl_matrix3dq_t *in); +/** + * @brief Do relu with clips for a quantized matrix + * + * @param in Input and output quantized matrix, data will be updated + * @param clip Float point value to limit the maximum data + */ void dl_matrix3dq_relu_clip(dl_matrix3dq_t *in, fptp_t clip); +/** + * @brief Do leaky relu for a quantized matrix + * + * @param in Input and output quantized matrix, data will be updated + * @param alpha Float point value to multiply for those less than zero + * @param clip Float point value to limit the maximum data + */ void dl_matrix3dq_leaky_relu(dl_matrix3dq_t *in, fptp_t alpha, fptp_t clip); +/** + * @brief Do prelu for a quantized matrix + * + * @param in Input and output quantized matrix, data will be updated + * @param alpha Quantized matrix to multiply for those less than zero + */ void dl_matrix3dq_p_relu(dl_matrix3dq_t *in, dl_matrix3dq_t *alpha); // // Concat // +/** + * @brief Concatenate two quantized matrix in channel + * + * @param in_1 Quantized matrix to be concatenated + * @param in_2 Quantized matrix to be concatenated + * @return Quantized matrix with the same width and height of in_1 and in_2, and with the sum of channel number of in_1 and in_2 + */ dl_matrix3dq_t *dl_matrix3dq_concat(dl_matrix3dq_t *in_1, dl_matrix3dq_t *in_2); +/** + * @brief Concatenate four quantized matrix in channel + * + * @param in_1 Quantized matrix to be concatenated + * @param in_2 Quantized matrix to be concatenated + * @param in_3 Quantized matrix to be concatenated + * @param in_4 Quantized matrix to be concatenated + * @return Quantized matrix with the same width and height of all inputs, and with the sum of channel number of all inputs + */ dl_matrix3dq_t *dl_matrix3dq_concat_4(dl_matrix3dq_t *in_1, dl_matrix3dq_t *in_2, dl_matrix3dq_t *in_3, dl_matrix3dq_t *in_4); +/** + * @brief Concatenate four quantized matrix in channel + * + * @param in_1 Quantized matrix to be concatenated + * @param in_2 Quantized matrix to be concatenated + * @param in_3 Quantized matrix to be concatenated + * @param in_4 Quantized matrix to be concatenated + * @param in_5 Quantized matrix to be concatenated + * @param in_6 Quantized matrix to be concatenated + * @param in_7 Quantized matrix to be concatenated + * @param in_8 Quantized matrix to be concatenated + * @return Quantized matrix with the same width and height of all inputs, and with the sum of channel number of all inputs + */ dl_matrix3dq_t *dl_matrix3dq_concat_8(dl_matrix3dq_t *in_1, dl_matrix3dq_t *in_2, dl_matrix3dq_t *in_3, @@ -135,16 +234,42 @@ dl_matrix3dq_t *dl_matrix3dq_concat_8(dl_matrix3dq_t *in_1, // // Conv 1x1 // +/** + * @brief Do 1x1 convolution with a quantized matrix + * + * @param out Preallocated quantized matrix, size (1, w, h, n) + * @param in Input matrix, size (1, w, h, c) + * @param filter 1x1 filter, size (n, 1, 1, c) + * @param mode Implementation mode + */ void dl_matrix3dqq_conv_1x1(dl_matrix3dq_t *out, dl_matrix3dq_t *in, dl_matrix3dq_t *filter, dl_conv_mode mode); +/** + * @brief Do 1x1 convolution with a quantized matrix, with relu activation + * + * @param out Preallocated quantized matrix, size (1, w, h, n) + * @param in Input matrix, size (1, w, h, c) + * @param filter 1x1 filter, size (n, 1, 1, c) + * @param mode Implementation mode + */ void dl_matrix3dqq_conv_1x1_with_relu(dl_matrix3dq_t *out, dl_matrix3dq_t *in, dl_matrix3dq_t *filter, dl_conv_mode mode); +/** + * @brief Do 1x1 convolution with a quantized matrix, with bias adding + * + * @param out Preallocated quantized matrix, size (1, w, h, n) + * @param in Input matrix, size (1, w, h, c) + * @param filter 1x1 filter, size (n, 1, 1, c) + * @param bias Bias, size (1, 1, 1, n) + * @param mode Implementation mode + * @param name Layer name to debug + */ void dl_matrix3dqq_conv_1x1_with_bias(dl_matrix3dq_t *out, dl_matrix3dq_t *in, dl_matrix3dq_t *filter, @@ -152,23 +277,49 @@ void dl_matrix3dqq_conv_1x1_with_bias(dl_matrix3dq_t *out, dl_conv_mode mode, char *name); -void dl_matrix3dqq_conv_1x1_with_prelu(dl_matrix3dq_t *out, - dl_matrix3dq_t *in, - dl_matrix3dq_t *filter, - dl_matrix3dq_t *prelu, - dl_conv_mode mode); - +/** + * @brief Do 1x1 convolution with a quantized matrix, with bias adding and relu activation + * + * @param out Preallocated quantized matrix, size (1, w, h, n) + * @param in Input matrix, size (1, w, h, c) + * @param filter 1x1 filter, size (n, 1, 1, c) + * @param bias Bias, size (1, 1, 1, n) + * @param mode Implementation mode + */ void dl_matrix3dqq_conv_1x1_with_bias_relu(dl_matrix3dq_t *out, dl_matrix3dq_t *in, dl_matrix3dq_t *filter, dl_matrix3dq_t *bias, dl_conv_mode mode); +void dl_matrix3dqq_conv_1x1_with_prelu(dl_matrix3dq_t *out, + dl_matrix3dq_t *in, + dl_matrix3dq_t *filter, + dl_matrix3dq_t *prelu, + dl_conv_mode mode); + +/** + * @brief Do 1x1 convolution with an 8-bit fixed point matrix + * + * @param out Preallocated quantized matrix, size (1, w, h, n) + * @param in Input matrix, size (1, w, h, c) + * @param filter 1x1 filter, size (n, 1, 1, c) + * @param mode Implementation mode + */ void dl_matrix3duq_conv_1x1(dl_matrix3dq_t *out, dl_matrix3du_t *in, dl_matrix3dq_t *filter, dl_conv_mode mode); +/** + * @brief Do 1x1 convolution with an 8-bit fixed point matrix, with bias adding + * + * @param out Preallocated quantized matrix, size (1, w, h, n) + * @param in Input matrix, size (1, w, h, c) + * @param filter 1x1 filter, size (n, 1, 1, c) + * @param bias Bias, size (1, 1, 1, n) + * @param mode Implementation mode + */ void dl_matrix3duq_conv_1x1_with_bias(dl_matrix3dq_t *out, dl_matrix3du_t *in, dl_matrix3dq_t *filter, @@ -178,12 +329,32 @@ void dl_matrix3duq_conv_1x1_with_bias(dl_matrix3dq_t *out, // // Conv 3x3 // +/** + * @brief Do 3x3 convolution basic operation with a quantized matrix + * + * @param out Preallocated quantized matrix + * @param in Input matrix, size (1, w, h, c) + * @param filter 3x3 filter, size (n, 3, 3, c) + * @param stride_x Stride of width + * @param stride_y Stride of height + */ void dl_matrix3dqq_conv_3x3_op(dl_matrix3dq_t *out, dl_matrix3dq_t *in, - dl_matrix3dq_t *f, + dl_matrix3dq_t *filter, int stride_x, int stride_y); +/** + * @brief Do 3x3 convolution with a quantized matrix + * + * @param in Input matrix, size (1, w, h, c) + * @param filter 3x3 filter, size (n, 3, 3, c) + * @param stride_x Stride of width + * @param stride_y Stride of height + * @param padding Padding type, 0: valid, 1: same + * @param exponent Exponent for resulting matrix + * @return Resulting quantized matrix + */ dl_matrix3dq_t *dl_matrix3dqq_conv_3x3(dl_matrix3dq_t *in, dl_matrix3dq_t *filter, int stride_x, @@ -191,6 +362,18 @@ dl_matrix3dq_t *dl_matrix3dqq_conv_3x3(dl_matrix3dq_t *in, dl_padding_type padding, int exponent); +/** + * @brief Do 3x3 convolution with a quantized matrix, with bias adding + * + * @param in Input matrix, size (1, w, h, c) + * @param filter 3x3 filter, size (n, 3, 3, c) + * @param bias Bias, size (1, 1, 1, n) + * @param stride_x Stride of width + * @param stride_y Stride of height + * @param padding Padding type, 0: valid, 1: same + * @param exponent Exponent for resulting matrix + * @return Resulting quantized matrix + */ dl_matrix3dq_t *dl_matrix3dqq_conv_3x3_with_bias(dl_matrix3dq_t *in, dl_matrix3dq_t *f, dl_matrix3dq_t *bias, @@ -224,7 +407,7 @@ dl_matrix3dq_t *dl_matrix3duq_conv_3x3_with_bias_prelu(dl_matrix3du_t *in, // /** - * @brief Do a general CNN layer pass, dimension is (number, width, height, channel) + * @brief Do a general convolution layer pass, size is (number, width, height, channel) * * @param in Input image * @param filter Weights of the neurons @@ -245,6 +428,19 @@ dl_matrix3dq_t *dl_matrix3dqq_conv_common(dl_matrix3dq_t *in, int exponent, dl_conv_mode mode); +/** + * @brief Do a general convolution layer pass for an 8-bit fixed point matrix, size is (number, width, height, channel) + * + * @param in Input image + * @param filter Weights of the neurons + * @param bias Bias for the CNN layer. + * @param stride_x The step length of the convolution window in x(width) direction + * @param stride_y The step length of the convolution window in y(height) direction + * @param padding One of VALID or SAME + * @param mode Do convolution using C implement or xtensa implement, 0 or 1, with respect. + * If ESP_PLATFORM is not defined, this value is not used. + * @return The result of CNN layer. + */ dl_matrix3dq_t *dl_matrix3duq_conv_common(dl_matrix3du_t *in, dl_matrix3dq_t *filter, dl_matrix3dq_t *bias, @@ -257,6 +453,17 @@ dl_matrix3dq_t *dl_matrix3duq_conv_common(dl_matrix3du_t *in, // // Depthwise 3x3 // +/** + * @brief Do 3x3 depthwise convolution with an 8-bit fixed point matrix + * + * @param in Input matrix, size (1, w, h, c) + * @param filter 3x3 filter, size (1, 3, 3, c) + * @param stride_x Stride of width + * @param stride_y Stride of height + * @param padding Padding type, 0: valid, 1: same + * @param exponent Exponent for resulting matrix + * @return Resulting quantized matrix + */ dl_matrix3dq_t *dl_matrix3duq_depthwise_conv_3x3(dl_matrix3du_t *in, dl_matrix3dq_t *filter, int stride_x, @@ -264,6 +471,17 @@ dl_matrix3dq_t *dl_matrix3duq_depthwise_conv_3x3(dl_matrix3du_t *in, dl_padding_type padding, int exponent); +/** + * @brief Do 3x3 depthwise convolution with a quantized matrix + * + * @param in Input matrix, size (1, w, h, c) + * @param filter 3x3 filter, size (1, 3, 3, c) + * @param stride_x Stride of width + * @param stride_y Stride of height + * @param padding Padding type, 0: valid, 1: same + * @param exponent Exponent for resulting matrix + * @return Resulting quantized matrix + */ dl_matrix3dq_t *dl_matrix3dqq_depthwise_conv_3x3(dl_matrix3dq_t *in, dl_matrix3dq_t *filter, int stride_x, @@ -287,14 +505,45 @@ dl_matrix3dq_t *dl_matrix3dqq_depthwise_conv_3x3_3(dl_matrix3dq_t *in, int exponent); #endif +/** + * @brief Do 3x3 depthwise convolution with a quantized matrix, with bias adding + * + * @param in Input matrix, size (1, w, h, c) + * @param filter 3x3 filter, size (1, 3, 3, c) + * @param bias Bias, size (1, 1, 1, c) + * @param stride_x Stride of width + * @param stride_y Stride of height + * @param padding Padding type, 0: valid, 1: same + * @param exponent Exponent for resulting matrix + * @param relu Whether to use relu activation + * @return Resulting quantized matrix + */ dl_matrix3dq_t *dl_matrix3dqq_depthwise_conv_3x3_with_bias(dl_matrix3dq_t *in, - dl_matrix3dq_t *f, - dl_matrix3dq_t *bias, - int stride_x, - int stride_y, - dl_padding_type padding, - int exponent, - int relu); + dl_matrix3dq_t *f, + dl_matrix3dq_t *bias, + int stride_x, + int stride_y, + dl_padding_type padding, + int exponent, + int relu); + +/** + * @brief Do 3x3 depthwise convolution with a quantized matrix, with bias adding and stride 1 + * + * @param in Input matrix, size (1, w, h, c) + * @param filter 3x3 filter, size (1, 3, 3, c) + * @param bias Bias, size (1, 1, 1, n) + * @param padding Padding type, 0: valid, 1: same + * @param exponent Exponent for resulting matrix + * @param relu Whether to use relu activation + * @return Resulting quantized matrix + */ +dl_matrix3dq_t *dl_matrix3dqq_depthwise_conv_3x3s1_with_bias(dl_matrix3dq_t *in, + dl_matrix3dq_t *f, + dl_matrix3dq_t *bias, + dl_padding_type padding, + int exponent, + int relu); dl_matrix3dq_t *dl_matrix3dqq_depthwise_conv_3x3_with_prelu(dl_matrix3dq_t *in, dl_matrix3dq_t *filter, @@ -304,12 +553,6 @@ dl_matrix3dq_t *dl_matrix3dqq_depthwise_conv_3x3_with_prelu(dl_matrix3dq_t *in, dl_padding_type padding, int exponent); -dl_matrix3dq_t *dl_matrix3dqq_depthwise_conv_3x3s1_with_bias(dl_matrix3dq_t *in, - dl_matrix3dq_t *f, - dl_matrix3dq_t *bias, - dl_padding_type padding, - int exponent, - int relu); // // Depthwise Common @@ -344,12 +587,28 @@ void dl_matrix3dqq_dot_product(dl_matrix3dq_t *out, // // FC // - +/** + * @brief Do fully connected layer forward. + * + * @param out Preallocated resulting matrix, size (1, 1, 1, h) + * @param in Input matrix, size (1, 1, 1, w) + * @param filter Filter matrix, size (1, w, h, 1) + * @param mode Implementation mode + */ void dl_matrix3dqq_fc(dl_matrix3dq_t *out, dl_matrix3dq_t *in, dl_matrix3dq_t *filter, dl_conv_mode mode); +/** + * @brief Do fully connected layer forward, with bias adding + * + * @param out Preallocated resulting matrix, size (1, 1, 1, h) + * @param in Input matrix, size (1, 1, 1, w) + * @param filter Filter matrix, size (1, w, h, 1) + * @param bias Bias matrix, size (1, 1, 1, h) + * @param mode Implementation mode + */ void dl_matrix3dqq_fc_with_bias(dl_matrix3dq_t *out, dl_matrix3dq_t *in, dl_matrix3dq_t *filter, @@ -360,7 +619,28 @@ void dl_matrix3dqq_fc_with_bias(dl_matrix3dq_t *out, // // Mobilefaceblock // - +/** + * @brief Do mobilefacenet process with splited pointwise 1x1 convolution, the process sequence is 1x1 pointwise->bn->relu->3x3 depthwise->bn->relu->1x1 pointwise->bn + * + * @param in Input matrix, size (1, w, h, c) + * @param pw_1 Pointwise 1x1 filter, size (n1/2, 1, 1, c) + * @param pw_2 Pointwise 1x1 filter, size (n1/2, 1, 1, c) + * @param pw_bias Pointwise bias, size (1, 1, 1, n1) + * @param dw Depthwise 3x3 filter, size (1, 3, 3, n1) + * @param dw_bias Depthwise bias, size (1, 1, 1, n1) + * @param pw_linear_1 Pointwise 1x1 filter, size (n2/2, 1, 1, n1) + * @param pw_linear_2 Pointwise 1x1 filter, size (n2/2, 1, 1, n1) + * @param pw_linear_bias Pointwise bias, size (1, 1, 1, n2) + * @param pw_exponent Exponent for pointwise resulting matrix + * @param dw_exponent Exponent for depthwise resulting matrix + * @param pw_linear_exponent Exponent for pointwise resulting matrix + * @param stride_x Stride of width + * @param stride_y Stride of height + * @param padding Padding type, 0: valid, 1: same + * @param mode Implementation mode + * @param shortcut Whether has a shortcut at pointwise linear + * @return Resulting quantized matrix + */ dl_matrix3dq_t *dl_matrix3dqq_mobilefaceblock_split(dl_matrix3dq_t *in, dl_matrix3dq_t *pw_1, dl_matrix3dq_t *pw_2, @@ -379,6 +659,26 @@ dl_matrix3dq_t *dl_matrix3dqq_mobilefaceblock_split(dl_matrix3dq_t *in, dl_conv_mode mode, int shortcut); +/** + * @brief Do mobilefacenet process, the process sequence is 1x1 pointwise->bn->relu->3x3 depthwise->bn->relu->1x1 pointwise->bn + * + * @param in Input matrix, size (1, w, h, c) + * @param pw Pointwise 1x1 filter, size (n1, 1, 1, c) + * @param pw_bias Pointwise bias, size (1, 1, 1, n1) + * @param dw Depthwise 3x3 filter, size (1, 3, 3, n1) + * @param dw_bias Depthwise bias, size (1, 1, 1, n1) + * @param pw_linear Pointwise 1x1 filter, size (n2, 1, 1, n1) + * @param pw_linear_bias Pointwise bias, size (1, 1, 1, n2) + * @param pw_exponent Exponent for pointwise resulting matrix + * @param dw_exponent Exponent for depthwise resulting matrix + * @param pw_linear_exponent Exponent for pointwise resulting matrix + * @param stride_x Stride of width + * @param stride_y Stride of height + * @param padding Padding type, 0: valid, 1: same + * @param mode Implementation mode + * @param shortcut Whether has a shortcut at pointwise linear + * @return Resulting quantized matrix + */ dl_matrix3dq_t *dl_matrix3dqq_mobilefaceblock(dl_matrix3dq_t *in, dl_matrix3dq_t *pw, dl_matrix3dq_t *pw_bias, @@ -399,6 +699,19 @@ dl_matrix3dq_t *dl_matrix3dqq_mobilefaceblock(dl_matrix3dq_t *in, // Mobilenet // +/** + * @brief Do mobilenet process, the process sequence is 1x1 dilated->prelu->3x3 depthwise->prelu->1x1 compress->bias + * + * @param in Input matrix, size (1, w, h, c) + * @param dilate Pointwise 1x1 filter, size (n1, 1, 1, c) + * @param dilate_prelu Pointwise prelu, size (1, 1, 1, n1) + * @param depthwise Depthwise 3x3 filter, size (1, 3, 3, n1) + * @param depthwise_prelu Depthwise prelu, size (1, 1, 1, n1) + * @param compress Pointwise 1x1 filter, size (n2, 1, 1, n1) + * @param bias Pointwise bias, size (1, 1, 1, n2) + * @param config Mobilenet configuration + * @return Resulting quantized matrix + */ dl_matrix3dq_t *dl_matrix3dqq_mobilenet(dl_matrix3dq_t *in, dl_matrix3dq_t *dilate, dl_matrix3dq_t *dilate_prelu, @@ -409,6 +722,19 @@ dl_matrix3dq_t *dl_matrix3dqq_mobilenet(dl_matrix3dq_t *in, dl_matrix3dq_mobilenet_config_t config, char *name); +/** + * @brief Do mobilenet process, the process sequence is 1x1 dilated->prelu->3x3 depthwise->prelu->1x1 compress->bias + * + * @param in Input matrix, 8-bit fixed point, size (1, w, h, c) + * @param dilate Pointwise 1x1 filter, size (n1, 1, 1, c) + * @param dilate_prelu Pointwise prelu, size (1, 1, 1, n1) + * @param depthwise Depthwise 3x3 filter, size (1, 3, 3, n1) + * @param depthwise_prelu Depthwise prelu, size (1, 1, 1, n1) + * @param compress Pointwise 1x1 filter, size (n2, 1, 1, n1) + * @param bias Pointwise bias, size (1, 1, 1, n2) + * @param config Mobilenet configuration + * @return Resulting quantized matrix + */ dl_matrix3dq_t *dl_matrix3duq_mobilenet(dl_matrix3du_t *in, dl_matrix3dq_t *dilate, dl_matrix3dq_t *dilate_prelu, @@ -444,5 +770,10 @@ dl_error_type dl_matrix3duq_padding(dl_matrix3du_t **padded_in, // // Pooling // - +/** + * @brief Calculate average value of a feature map + * + * @param in Input matrix, size (1, w, h, c) + * @return Resulting matrix, size (1, 1, 1, c) + */ dl_matrix3dq_t *dl_matrix3dq_global_pool(dl_matrix3dq_t *in); diff --git a/tools/sdk/include/esp-face/frmn.h b/tools/sdk/include/esp-face/frmn.h index afdd253afcc..171f69ad885 100644 --- a/tools/sdk/include/esp-face/frmn.h +++ b/tools/sdk/include/esp-face/frmn.h @@ -9,23 +9,47 @@ extern "C" #include "dl_lib_matrix3dq.h" /** - * @brief - * - * @param in - * @return dl_matrix3d_t* + * @brief Forward the face recognition process with frmn model. Calculate in float. + * + * @param in Image matrix, rgb888 format, size is 56x56, normalized + * @return dl_matrix3d_t* Face ID feature vector, size is 512 */ dl_matrix3d_t *frmn(dl_matrix3d_t *in); /** - * @brief - * - * @param in - * @return dl_matrix3dq_t* + * @brief Forward the face recognition process with frmn model. Calculate in quantization. + * + * @param in Image matrix, rgb888 format, size is 56x56, normalized + * @param mode 0: C implement; 1: handwrite xtensa instruction implement + * @return Face ID feature vector, size is 512 */ dl_matrix3dq_t *frmn_q(dl_matrix3dq_t *in, dl_conv_mode mode); + /** + * @brief Forward the face recognition process with frmn2 model. Calculate in quantization. + * + * @param in Image matrix, rgb888 format, size is 56x56, normalized + * @param mode 0: C implement; 1: handwrite xtensa instruction implement + * @return Face ID feature vector, size is 512 + */ dl_matrix3dq_t *frmn2_q(dl_matrix3dq_t *in, dl_conv_mode mode); + + /** + * @brief Forward the face recognition process with frmn2p model. Calculate in quantization. + * + * @param in Image matrix, rgb888 format, size is 56x56, normalized + * @param mode 0: C implement; 1: handwrite xtensa instruction implement + * @return Face ID feature vector, size is 512 + */ dl_matrix3dq_t *frmn2p_q(dl_matrix3dq_t *in, dl_conv_mode mode); + + /** + * @brief Forward the face recognition process with frmn2c model. Calculate in quantization. + * + * @param in Image matrix, rgb888 format, size is 56x56, normalized + * @param mode 0: C implement; 1: handwrite xtensa instruction implement + * @return Face ID feature vector, size is 512 + */ dl_matrix3dq_t *frmn2c_q(dl_matrix3dq_t *in, dl_conv_mode mode); #if __cplusplus diff --git a/tools/sdk/include/esp-face/mtmn.h b/tools/sdk/include/esp-face/mtmn.h index 144a5b97082..609a82ea488 100644 --- a/tools/sdk/include/esp-face/mtmn.h +++ b/tools/sdk/include/esp-face/mtmn.h @@ -30,18 +30,33 @@ extern "C" #include "dl_lib_matrix3d.h" #include "dl_lib_matrix3dq.h" + /** + * Detection results with MTMN. + * + */ typedef struct { - dl_matrix3d_t *category; - dl_matrix3d_t *offset; - dl_matrix3d_t *landmark; + dl_matrix3d_t *category; /*!< Classification result after softmax, channel is 2 */ + dl_matrix3d_t *offset; /*!< Bounding box offset of 2 points: top-left and bottom-right, channel is 4 */ + dl_matrix3d_t *landmark; /*!< Offsets of 5 landmarks: + * - Left eye + * - Mouth leftside + * - Nose + * - Right eye + * - Mouth rightside + * + * channel is 10 + * */ } mtmn_net_t; + /** * @brief Free a mtmn_net_t * * @param p A mtmn_net_t pointer + * */ + void mtmn_net_t_free(mtmn_net_t *p); /** diff --git a/tools/sdk/include/esp32/esp_dport_access.h b/tools/sdk/include/esp32/esp_dport_access.h index adbb8282012..8ea60c4cdb0 100644 --- a/tools/sdk/include/esp32/esp_dport_access.h +++ b/tools/sdk/include/esp32/esp_dport_access.h @@ -33,7 +33,7 @@ uint32_t esp_dport_access_sequence_reg_read(uint32_t reg); //only call in case of panic(). void esp_dport_access_int_abort(void); -#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) +#if defined(BOOTLOADER_BUILD) || !defined(CONFIG_ESP32_DPORT_WORKAROUND) || !defined(ESP_PLATFORM) #define DPORT_STALL_OTHER_CPU_START() #define DPORT_STALL_OTHER_CPU_END() #define DPORT_INTERRUPT_DISABLE() @@ -41,7 +41,7 @@ void esp_dport_access_int_abort(void); #else #define DPORT_STALL_OTHER_CPU_START() esp_dport_access_stall_other_cpu_start() #define DPORT_STALL_OTHER_CPU_END() esp_dport_access_stall_other_cpu_end() -#define DPORT_INTERRUPT_DISABLE() unsigned int intLvl = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL) +#define DPORT_INTERRUPT_DISABLE() unsigned int intLvl = XTOS_SET_INTLEVEL(CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL) #define DPORT_INTERRUPT_RESTORE() XTOS_RESTORE_JUST_INTLEVEL(intLvl) #endif diff --git a/tools/sdk/include/json/cJSON.h b/tools/sdk/include/json/cJSON.h index 52101e11793..592986b86e9 100644 --- a/tools/sdk/include/json/cJSON.h +++ b/tools/sdk/include/json/cJSON.h @@ -28,10 +28,60 @@ extern "C" { #endif +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif + +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +#define CJSON_CDECL __cdecl +#define CJSON_STDCALL __stdcall + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type CJSON_STDCALL +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#endif +#else /* !__WINDOWS__ */ +#define CJSON_CDECL +#define CJSON_STDCALL + +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + /* project version */ #define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 1 +#define CJSON_VERSION_PATCH 12 #include @@ -74,55 +124,13 @@ typedef struct cJSON typedef struct cJSON_Hooks { - void *(*malloc_fn)(size_t sz); - void (*free_fn)(void *ptr); + /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ + void *(CJSON_CDECL *malloc_fn)(size_t sz); + void (CJSON_CDECL *free_fn)(void *ptr); } cJSON_Hooks; typedef int cJSON_bool; -#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) -#define __WINDOWS__ -#endif -#ifdef __WINDOWS__ - -/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options: - -CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols -CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) -CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol - -For *nix builds that support visibility attribute, you can define similar behavior by - -setting default visibility to hidden by adding --fvisibility=hidden (for gcc) -or --xldscope=hidden (for sun cc) -to CFLAGS - -then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does - -*/ - -/* export symbols by default, this is necessary for copy pasting the C and header file */ -#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_EXPORT_SYMBOLS -#endif - -#if defined(CJSON_HIDE_SYMBOLS) -#define CJSON_PUBLIC(type) type __stdcall -#elif defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall -#elif defined(CJSON_IMPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall -#endif -#else /* !WIN32 */ -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) -#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type -#else -#define CJSON_PUBLIC(type) type -#endif -#endif - /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. * This is to prevent stack overflows. */ #ifndef CJSON_NESTING_LIMIT @@ -156,7 +164,7 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); /* Returns the number of items in an array (or object). */ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); -/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); /* Get item "string" from object. Case insensitive. */ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); diff --git a/tools/sdk/include/json/cJSON_Utils.h b/tools/sdk/include/json/cJSON_Utils.h index 03ec10c9e2c..a970c650467 100644 --- a/tools/sdk/include/json/cJSON_Utils.h +++ b/tools/sdk/include/json/cJSON_Utils.h @@ -20,6 +20,14 @@ THE SOFTWARE. */ +#ifndef cJSON_Utils__h +#define cJSON_Utils__h + +#ifdef __cplusplus +extern "C" +{ +#endif + #include "cJSON.h" /* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */ @@ -72,3 +80,9 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje /* Sorts the members of the object into alphabetical order. */ CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object); CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/sdk/include/soc/soc/dport_access.h b/tools/sdk/include/soc/soc/dport_access.h index 00e7c838105..2639e46ef14 100644 --- a/tools/sdk/include/soc/soc/dport_access.h +++ b/tools/sdk/include/soc/soc/dport_access.h @@ -48,7 +48,7 @@ extern "C" { // After completing read operations, use DPORT_STALL_OTHER_CPU_END(). // This method uses stall other CPU while reading DPORT registers. // Useful for compatibility, as well as for large consecutive readings. -// This method is slower, but must be used if ROM functions or +// This method is slower, but must be used if ROM functions or // other code is called which accesses DPORT without any other workaround. // *) The pre-readable APB register before reading the DPORT register // helps synchronize the operation of the two CPUs, @@ -73,7 +73,7 @@ extern "C" { */ static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg) { -#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) +#if defined(BOOTLOADER_BUILD) || !defined(CONFIG_ESP32_DPORT_WORKAROUND) || !defined(ESP_PLATFORM) return _DPORT_REG_READ(reg); #else return esp_dport_access_reg_read(reg); @@ -106,7 +106,7 @@ static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg) */ static inline uint32_t IRAM_ATTR DPORT_SEQUENCE_REG_READ(uint32_t reg) { -#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) +#if defined(BOOTLOADER_BUILD) || !defined(CONFIG_ESP32_DPORT_WORKAROUND) || !defined(ESP_PLATFORM) return _DPORT_REG_READ(reg); #else return esp_dport_access_sequence_reg_read(reg); @@ -166,7 +166,7 @@ static inline uint32_t IRAM_ATTR DPORT_SEQUENCE_REG_READ(uint32_t reg) */ static inline uint32_t IRAM_ATTR DPORT_READ_PERI_REG(uint32_t reg) { -#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) +#if defined(BOOTLOADER_BUILD) || !defined(CONFIG_ESP32_DPORT_WORKAROUND) || !defined(ESP_PLATFORM) return _DPORT_REG_READ(reg); #else return esp_dport_access_reg_read(reg); diff --git a/tools/sdk/include/soc/soc/soc.h b/tools/sdk/include/soc/soc/soc.h index 96dea802324..d1d468303cc 100644 --- a/tools/sdk/include/soc/soc/soc.h +++ b/tools/sdk/include/soc/soc/soc.h @@ -147,7 +147,7 @@ #define IS_DPORT_REG(_r) (((_r) >= DR_REG_DPORT_BASE) && (_r) <= DR_REG_DPORT_END) -#if !defined( BOOTLOADER_BUILD ) && !defined( CONFIG_FREERTOS_UNICORE ) && defined( ESP_PLATFORM ) +#if !defined( BOOTLOADER_BUILD ) && defined( CONFIG_ESP32_DPORT_WORKAROUND ) && defined( ESP_PLATFORM ) #define ASSERT_IF_DPORT_REG(_r, OP) TRY_STATIC_ASSERT(!IS_DPORT_REG(_r), (Cannot use OP for DPORT registers use DPORT_##OP)); #else #define ASSERT_IF_DPORT_REG(_r, OP) diff --git a/tools/sdk/lib/libapp_trace.a b/tools/sdk/lib/libapp_trace.a index fd4556cb532..4857b5afedf 100644 Binary files a/tools/sdk/lib/libapp_trace.a and b/tools/sdk/lib/libapp_trace.a differ diff --git a/tools/sdk/lib/libapp_update.a b/tools/sdk/lib/libapp_update.a index 7feaa11090a..9ead7d8c63c 100644 Binary files a/tools/sdk/lib/libapp_update.a and b/tools/sdk/lib/libapp_update.a differ diff --git a/tools/sdk/lib/libasio.a b/tools/sdk/lib/libasio.a index bf1dbe4546c..857fbae184a 100644 Binary files a/tools/sdk/lib/libasio.a and b/tools/sdk/lib/libasio.a differ diff --git a/tools/sdk/lib/libbootloader_support.a b/tools/sdk/lib/libbootloader_support.a index bb24c7493ff..465f3e83efc 100644 Binary files a/tools/sdk/lib/libbootloader_support.a and b/tools/sdk/lib/libbootloader_support.a differ diff --git a/tools/sdk/lib/libbt.a b/tools/sdk/lib/libbt.a index 06b85b67b4e..4f0ffdefc7e 100644 Binary files a/tools/sdk/lib/libbt.a and b/tools/sdk/lib/libbt.a differ diff --git a/tools/sdk/lib/libcoap.a b/tools/sdk/lib/libcoap.a index 9b8b4829abe..854b45b8587 100644 Binary files a/tools/sdk/lib/libcoap.a and b/tools/sdk/lib/libcoap.a differ diff --git a/tools/sdk/lib/libconsole.a b/tools/sdk/lib/libconsole.a index a0218aafd28..cb2986480ea 100644 Binary files a/tools/sdk/lib/libconsole.a and b/tools/sdk/lib/libconsole.a differ diff --git a/tools/sdk/lib/libcxx.a b/tools/sdk/lib/libcxx.a index 0340b578f8c..1389afedb3e 100644 Binary files a/tools/sdk/lib/libcxx.a and b/tools/sdk/lib/libcxx.a differ diff --git a/tools/sdk/lib/libdl_lib.a b/tools/sdk/lib/libdl_lib.a index 3bb387790c1..9a186595d35 100644 Binary files a/tools/sdk/lib/libdl_lib.a and b/tools/sdk/lib/libdl_lib.a differ diff --git a/tools/sdk/lib/libdriver.a b/tools/sdk/lib/libdriver.a index a14d3e2cded..278349e0369 100644 Binary files a/tools/sdk/lib/libdriver.a and b/tools/sdk/lib/libdriver.a differ diff --git a/tools/sdk/lib/libesp-tls.a b/tools/sdk/lib/libesp-tls.a index 07054b291d9..9cc139c78ab 100644 Binary files a/tools/sdk/lib/libesp-tls.a and b/tools/sdk/lib/libesp-tls.a differ diff --git a/tools/sdk/lib/libesp32-camera.a b/tools/sdk/lib/libesp32-camera.a index cf852898c56..1c0179837bc 100644 Binary files a/tools/sdk/lib/libesp32-camera.a and b/tools/sdk/lib/libesp32-camera.a differ diff --git a/tools/sdk/lib/libesp32.a b/tools/sdk/lib/libesp32.a index a64f27e428d..240c82e4e22 100644 Binary files a/tools/sdk/lib/libesp32.a and b/tools/sdk/lib/libesp32.a differ diff --git a/tools/sdk/lib/libesp_adc_cal.a b/tools/sdk/lib/libesp_adc_cal.a index 49ec7e6760c..b55ca617858 100644 Binary files a/tools/sdk/lib/libesp_adc_cal.a and b/tools/sdk/lib/libesp_adc_cal.a differ diff --git a/tools/sdk/lib/libesp_event.a b/tools/sdk/lib/libesp_event.a index a0997d98466..60ca34ef7b0 100644 Binary files a/tools/sdk/lib/libesp_event.a and b/tools/sdk/lib/libesp_event.a differ diff --git a/tools/sdk/lib/libesp_http_client.a b/tools/sdk/lib/libesp_http_client.a index d34294f8321..a3f1ba83be8 100644 Binary files a/tools/sdk/lib/libesp_http_client.a and b/tools/sdk/lib/libesp_http_client.a differ diff --git a/tools/sdk/lib/libesp_http_server.a b/tools/sdk/lib/libesp_http_server.a index de1a4f76eb5..6637f05562f 100644 Binary files a/tools/sdk/lib/libesp_http_server.a and b/tools/sdk/lib/libesp_http_server.a differ diff --git a/tools/sdk/lib/libesp_https_ota.a b/tools/sdk/lib/libesp_https_ota.a index a3a5b14bb1d..3df5593397d 100644 Binary files a/tools/sdk/lib/libesp_https_ota.a and b/tools/sdk/lib/libesp_https_ota.a differ diff --git a/tools/sdk/lib/libesp_ringbuf.a b/tools/sdk/lib/libesp_ringbuf.a index e9e3179f94f..41d5e52285e 100644 Binary files a/tools/sdk/lib/libesp_ringbuf.a and b/tools/sdk/lib/libesp_ringbuf.a differ diff --git a/tools/sdk/lib/libethernet.a b/tools/sdk/lib/libethernet.a index 1739f7d623e..4c41f923816 100644 Binary files a/tools/sdk/lib/libethernet.a and b/tools/sdk/lib/libethernet.a differ diff --git a/tools/sdk/lib/libexpat.a b/tools/sdk/lib/libexpat.a index 3bee0694821..419c8c37270 100644 Binary files a/tools/sdk/lib/libexpat.a and b/tools/sdk/lib/libexpat.a differ diff --git a/tools/sdk/lib/libface_detection.a b/tools/sdk/lib/libface_detection.a index 3902f3e1ba5..b5d9868e456 100644 Binary files a/tools/sdk/lib/libface_detection.a and b/tools/sdk/lib/libface_detection.a differ diff --git a/tools/sdk/lib/libface_recognition.a b/tools/sdk/lib/libface_recognition.a index 845d3b311cb..b5f4486e729 100644 Binary files a/tools/sdk/lib/libface_recognition.a and b/tools/sdk/lib/libface_recognition.a differ diff --git a/tools/sdk/lib/libfatfs.a b/tools/sdk/lib/libfatfs.a index de02e657aee..7a5f329ec63 100644 Binary files a/tools/sdk/lib/libfatfs.a and b/tools/sdk/lib/libfatfs.a differ diff --git a/tools/sdk/lib/libfb_gfx.a b/tools/sdk/lib/libfb_gfx.a index 32e1251e7e0..a2967139948 100644 Binary files a/tools/sdk/lib/libfb_gfx.a and b/tools/sdk/lib/libfb_gfx.a differ diff --git a/tools/sdk/lib/libfd.a b/tools/sdk/lib/libfd.a index 9195fc55c6e..38ccff621f3 100644 Binary files a/tools/sdk/lib/libfd.a and b/tools/sdk/lib/libfd.a differ diff --git a/tools/sdk/lib/libfr.a b/tools/sdk/lib/libfr.a index 0c1b76b78f7..7ba16b25495 100644 Binary files a/tools/sdk/lib/libfr.a and b/tools/sdk/lib/libfr.a differ diff --git a/tools/sdk/lib/libfreemodbus.a b/tools/sdk/lib/libfreemodbus.a index 3142ba6b9c1..d64373bc699 100644 Binary files a/tools/sdk/lib/libfreemodbus.a and b/tools/sdk/lib/libfreemodbus.a differ diff --git a/tools/sdk/lib/libfreertos.a b/tools/sdk/lib/libfreertos.a index 2ed18663b85..1eed10babc2 100644 Binary files a/tools/sdk/lib/libfreertos.a and b/tools/sdk/lib/libfreertos.a differ diff --git a/tools/sdk/lib/libheap.a b/tools/sdk/lib/libheap.a index d2f9cc96f87..56e829a4bb4 100644 Binary files a/tools/sdk/lib/libheap.a and b/tools/sdk/lib/libheap.a differ diff --git a/tools/sdk/lib/libimage_util.a b/tools/sdk/lib/libimage_util.a index e389ce2b848..a8a38c9346c 100644 Binary files a/tools/sdk/lib/libimage_util.a and b/tools/sdk/lib/libimage_util.a differ diff --git a/tools/sdk/lib/libjsmn.a b/tools/sdk/lib/libjsmn.a index 0294befe7c4..c86b126d392 100644 Binary files a/tools/sdk/lib/libjsmn.a and b/tools/sdk/lib/libjsmn.a differ diff --git a/tools/sdk/lib/libjson.a b/tools/sdk/lib/libjson.a index 9e7b190a7b3..cd0768f7352 100644 Binary files a/tools/sdk/lib/libjson.a and b/tools/sdk/lib/libjson.a differ diff --git a/tools/sdk/lib/liblibsodium.a b/tools/sdk/lib/liblibsodium.a index a33df1981ac..f26b48d8f88 100644 Binary files a/tools/sdk/lib/liblibsodium.a and b/tools/sdk/lib/liblibsodium.a differ diff --git a/tools/sdk/lib/liblog.a b/tools/sdk/lib/liblog.a index c912533ebce..9e689004b2d 100644 Binary files a/tools/sdk/lib/liblog.a and b/tools/sdk/lib/liblog.a differ diff --git a/tools/sdk/lib/liblwip.a b/tools/sdk/lib/liblwip.a index 7904c4ace73..7b5d5bf5987 100644 Binary files a/tools/sdk/lib/liblwip.a and b/tools/sdk/lib/liblwip.a differ diff --git a/tools/sdk/lib/libmbedtls.a b/tools/sdk/lib/libmbedtls.a index e85972e9fa7..45929d70ac3 100644 Binary files a/tools/sdk/lib/libmbedtls.a and b/tools/sdk/lib/libmbedtls.a differ diff --git a/tools/sdk/lib/libmdns.a b/tools/sdk/lib/libmdns.a index e3e685664b8..8e4482766d0 100644 Binary files a/tools/sdk/lib/libmdns.a and b/tools/sdk/lib/libmdns.a differ diff --git a/tools/sdk/lib/libmicro-ecc.a b/tools/sdk/lib/libmicro-ecc.a index 66f712b02f8..3d3e108fed8 100644 Binary files a/tools/sdk/lib/libmicro-ecc.a and b/tools/sdk/lib/libmicro-ecc.a differ diff --git a/tools/sdk/lib/libmqtt.a b/tools/sdk/lib/libmqtt.a index 98344cc9007..18fd9420709 100644 Binary files a/tools/sdk/lib/libmqtt.a and b/tools/sdk/lib/libmqtt.a differ diff --git a/tools/sdk/lib/libnewlib.a b/tools/sdk/lib/libnewlib.a index 37136fddc52..640e1500160 100644 Binary files a/tools/sdk/lib/libnewlib.a and b/tools/sdk/lib/libnewlib.a differ diff --git a/tools/sdk/lib/libnghttp.a b/tools/sdk/lib/libnghttp.a index 8bfd8d1fb87..8ce8eb813fd 100644 Binary files a/tools/sdk/lib/libnghttp.a and b/tools/sdk/lib/libnghttp.a differ diff --git a/tools/sdk/lib/libnvs_flash.a b/tools/sdk/lib/libnvs_flash.a index d71b82cba6f..f2189ae77bb 100644 Binary files a/tools/sdk/lib/libnvs_flash.a and b/tools/sdk/lib/libnvs_flash.a differ diff --git a/tools/sdk/lib/libopenssl.a b/tools/sdk/lib/libopenssl.a index bf68995d513..935ee46a97f 100644 Binary files a/tools/sdk/lib/libopenssl.a and b/tools/sdk/lib/libopenssl.a differ diff --git a/tools/sdk/lib/libprotobuf-c.a b/tools/sdk/lib/libprotobuf-c.a index e0921da39a7..777e595da5d 100644 Binary files a/tools/sdk/lib/libprotobuf-c.a and b/tools/sdk/lib/libprotobuf-c.a differ diff --git a/tools/sdk/lib/libprotocomm.a b/tools/sdk/lib/libprotocomm.a index ed9ef7c9f77..a2d802e3967 100644 Binary files a/tools/sdk/lib/libprotocomm.a and b/tools/sdk/lib/libprotocomm.a differ diff --git a/tools/sdk/lib/libpthread.a b/tools/sdk/lib/libpthread.a index 624bb355ffd..6fba7a72a96 100644 Binary files a/tools/sdk/lib/libpthread.a and b/tools/sdk/lib/libpthread.a differ diff --git a/tools/sdk/lib/libsdmmc.a b/tools/sdk/lib/libsdmmc.a index 48f80d84725..4141d2688e0 100644 Binary files a/tools/sdk/lib/libsdmmc.a and b/tools/sdk/lib/libsdmmc.a differ diff --git a/tools/sdk/lib/libsmartconfig_ack.a b/tools/sdk/lib/libsmartconfig_ack.a index 5e736dd9dcd..ef0430902a8 100644 Binary files a/tools/sdk/lib/libsmartconfig_ack.a and b/tools/sdk/lib/libsmartconfig_ack.a differ diff --git a/tools/sdk/lib/libsoc.a b/tools/sdk/lib/libsoc.a index d80523ca42c..6dffcda805e 100644 Binary files a/tools/sdk/lib/libsoc.a and b/tools/sdk/lib/libsoc.a differ diff --git a/tools/sdk/lib/libspi_flash.a b/tools/sdk/lib/libspi_flash.a index e99f638c2c0..c8ae07321eb 100644 Binary files a/tools/sdk/lib/libspi_flash.a and b/tools/sdk/lib/libspi_flash.a differ diff --git a/tools/sdk/lib/libspiffs.a b/tools/sdk/lib/libspiffs.a index dff38e5e4d5..441ee6cdad0 100644 Binary files a/tools/sdk/lib/libspiffs.a and b/tools/sdk/lib/libspiffs.a differ diff --git a/tools/sdk/lib/libtcp_transport.a b/tools/sdk/lib/libtcp_transport.a index 1c5dd3fa9ae..1a46d0147a7 100644 Binary files a/tools/sdk/lib/libtcp_transport.a and b/tools/sdk/lib/libtcp_transport.a differ diff --git a/tools/sdk/lib/libtcpip_adapter.a b/tools/sdk/lib/libtcpip_adapter.a index f4a74b0721d..653e79b5b7e 100644 Binary files a/tools/sdk/lib/libtcpip_adapter.a and b/tools/sdk/lib/libtcpip_adapter.a differ diff --git a/tools/sdk/lib/libulp.a b/tools/sdk/lib/libulp.a index 2c37c7a6c50..c5c875fa529 100644 Binary files a/tools/sdk/lib/libulp.a and b/tools/sdk/lib/libulp.a differ diff --git a/tools/sdk/lib/libvfs.a b/tools/sdk/lib/libvfs.a index 326b2bcfe41..6c29a20e660 100644 Binary files a/tools/sdk/lib/libvfs.a and b/tools/sdk/lib/libvfs.a differ diff --git a/tools/sdk/lib/libwear_levelling.a b/tools/sdk/lib/libwear_levelling.a index 9641d5896f4..75c615a1bf6 100644 Binary files a/tools/sdk/lib/libwear_levelling.a and b/tools/sdk/lib/libwear_levelling.a differ diff --git a/tools/sdk/lib/libwifi_provisioning.a b/tools/sdk/lib/libwifi_provisioning.a index f347dae9f42..cccbbb0f7cf 100644 Binary files a/tools/sdk/lib/libwifi_provisioning.a and b/tools/sdk/lib/libwifi_provisioning.a differ diff --git a/tools/sdk/lib/libwpa_supplicant.a b/tools/sdk/lib/libwpa_supplicant.a index 5631572f24c..15535d887ec 100644 Binary files a/tools/sdk/lib/libwpa_supplicant.a and b/tools/sdk/lib/libwpa_supplicant.a differ diff --git a/tools/sdk/lib/libxtensa-debug-module.a b/tools/sdk/lib/libxtensa-debug-module.a index 34567ef6258..6b32ff1dce0 100644 Binary files a/tools/sdk/lib/libxtensa-debug-module.a and b/tools/sdk/lib/libxtensa-debug-module.a differ diff --git a/tools/sdk/sdkconfig b/tools/sdk/sdkconfig index 97cab6898f5..08e8142f7a4 100644 --- a/tools/sdk/sdkconfig +++ b/tools/sdk/sdkconfig @@ -2,6 +2,7 @@ # Automatically generated file; DO NOT EDIT. # Espressif IoT Development Framework Configuration # +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 # # SDK tool configuration @@ -272,6 +273,12 @@ CONFIG_FRMN2C_QUANT= # # ESP32-specific # +CONFIG_ESP32_REV_MIN_0=y +CONFIG_ESP32_REV_MIN_1= +CONFIG_ESP32_REV_MIN_2= +CONFIG_ESP32_REV_MIN_3= +CONFIG_ESP32_REV_MIN=0 +CONFIG_ESP32_DPORT_WORKAROUND=y CONFIG_ESP32_DEFAULT_CPU_FREQ_80= CONFIG_ESP32_DEFAULT_CPU_FREQ_160= CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y @@ -386,6 +393,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE= CONFIG_ESP_TIMER_PROFILING= CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5 # # Wi-Fi diff --git a/variants/magicbit/pins_arduino.h b/variants/magicbit/pins_arduino.h index 4f496860bf2..3073ade6100 100644 --- a/variants/magicbit/pins_arduino.h +++ b/variants/magicbit/pins_arduino.h @@ -54,16 +54,16 @@ static const uint8_t DAC1 = 25; static const uint8_t DAC2 = 26; static const uint8_t BUZZER = 25; -static const uint8_t RED_LED = 32; -static const uint8_t YELLOW_LED = 33; +static const uint8_t RED_LED = 27; +static const uint8_t YELLOW_LED = 18; static const uint8_t GREEN_LED = 16; static const uint8_t BLUE_LED = 17; static const uint8_t LDR = 36; static const uint8_t POT = 39; static const uint8_t RIGHT_PUTTON = 34; static const uint8_t LEFT_BUTTON = 35; -static const uint8_t MOTOR1A = 32; -static const uint8_t MOTOR1B = 33; +static const uint8_t MOTOR1A = 27; +static const uint8_t MOTOR1B = 18; static const uint8_t MOTOR2A = 16; static const uint8_t MOTOR2B = 17; static const uint8_t LED_BUILTIN=16; diff --git a/variants/vintlabsdevkitv1/pins_arduino.h b/variants/vintlabsdevkitv1/pins_arduino.h new file mode 100644 index 00000000000..e9cdd317b10 --- /dev/null +++ b/variants/vintlabsdevkitv1/pins_arduino.h @@ -0,0 +1,69 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define EXTERNAL_NUM_INTERRUPTS 16 +#define NUM_DIGITAL_PINS 40 +#define NUM_ANALOG_INPUTS 16 + +#define analogInputToDigitalPin(p) (((p)<20)?(esp32_adc2gpio[(p)]):-1) +#define digitalPinToInterrupt(p) (((p)<40)?(p):-1) +#define digitalPinHasPWM(p) (p < 34) + +static const uint8_t LED_BUILTIN = 2; +#define BUILTIN_LED LED_BUILTIN // backward compatibility + +static const uint8_t TX = 1; +static const uint8_t RX = 3; + +static const uint8_t SDA = 21; +static const uint8_t SCL = 22; + +static const uint8_t SS = 5; +static const uint8_t MOSI = 23; +static const uint8_t MISO = 19; +static const uint8_t SCK = 18; + +static const uint8_t A0 = 36; +static const uint8_t A3 = 39; +static const uint8_t A4 = 32; +static const uint8_t A5 = 33; +static const uint8_t A6 = 34; +static const uint8_t A7 = 35; +static const uint8_t A10 = 4; +static const uint8_t A11 = 0; +static const uint8_t A12 = 2; +static const uint8_t A13 = 15; +static const uint8_t A14 = 13; +static const uint8_t A15 = 12; +static const uint8_t A16 = 14; +static const uint8_t A17 = 27; +static const uint8_t A18 = 25; +static const uint8_t A19 = 26; + +static const uint8_t T0 = 4; +static const uint8_t T1 = 0; +static const uint8_t T2 = 2; +static const uint8_t T3 = 15; +static const uint8_t T4 = 13; +static const uint8_t T5 = 12; +static const uint8_t T6 = 14; +static const uint8_t T7 = 27; +static const uint8_t T8 = 33; +static const uint8_t T9 = 32; + +static const uint8_t DAC1 = 25; +static const uint8_t DAC2 = 26; + +// PWM Driver pins for PWM Driver board +static const uint8_t PWM0 = 12; +static const uint8_t PWM1 = 13; +static const uint8_t PWM2 = 14; +static const uint8_t PWM3 = 15; +static const uint8_t PWM4 = 16; +static const uint8_t PWM5 = 17; +static const uint8_t PWM6 = 18; +static const uint8_t PWM7 = 19; + +#endif /* Pins_Arduino_h */