Merge tag '2.1.2'
This commit is contained in:
		
							
								
								
									
										171
									
								
								buildroot/bin/build_all_examples
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										171
									
								
								buildroot/bin/build_all_examples
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,171 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
#
 | 
			
		||||
# Usage:
 | 
			
		||||
#
 | 
			
		||||
#  build_all_examples [-b|--branch=<branch>] - Branch to fetch from Configurations repo
 | 
			
		||||
#                     [-c|--continue]        - Continue the paused build
 | 
			
		||||
#                     [-d|--debug]           - Print extra debug output
 | 
			
		||||
#                     [-i|--ini]             - Archive ini/json/yml files in the temp config folder
 | 
			
		||||
#                     [-l|--limit=#]         - Limit the number of builds in this run
 | 
			
		||||
#                     [-n|--nobuild]         - Don't actually build anything.
 | 
			
		||||
#                     [-r|--resume=<path>]   - Start at some config in the filesystem order
 | 
			
		||||
#                     [-s|--skip]            - Do the thing
 | 
			
		||||
#
 | 
			
		||||
# build_all_examples [...] branch [resume-from]
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
. mfutil
 | 
			
		||||
 | 
			
		||||
GITREPO=https://github.com/MarlinFirmware/Configurations.git
 | 
			
		||||
STAT_FILE=./.pio/.buildall
 | 
			
		||||
 | 
			
		||||
usage() { echo "
 | 
			
		||||
Usage: $SELF [-b|--branch=<branch>] [-d|--debug] [-i|--ini] [-r|--resume=<path>]
 | 
			
		||||
       $SELF [-b|--branch=<branch>] [-d|--debug] [-i|--ini] [-c|--continue]
 | 
			
		||||
       $SELF [-b|--branch=<branch>] [-d|--debug] [-i|--ini] [-s|--skip]
 | 
			
		||||
       $SELF [-b|--branch=<branch>] [-d|--debug] [-n|--nobuild]
 | 
			
		||||
       $SELF [...] branch [resume-point]
 | 
			
		||||
"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Assume the most recent configs
 | 
			
		||||
BRANCH=import-2.1.x
 | 
			
		||||
unset FIRST_CONF
 | 
			
		||||
EXIT_USAGE=
 | 
			
		||||
LIMIT=1000
 | 
			
		||||
 | 
			
		||||
while getopts 'b:cdhil:nqr:sv-:' OFLAG; do
 | 
			
		||||
  case "${OFLAG}" in
 | 
			
		||||
    b) BRANCH=$OPTARG       ; bugout "Branch: $BRANCH" ;;
 | 
			
		||||
    r) FIRST_CONF="$OPTARG" ; bugout "Resume: $FIRST_CONF" ;;
 | 
			
		||||
    c) CONTINUE=1           ; bugout "Continue" ;;
 | 
			
		||||
    s) CONTSKIP=1           ; bugout "Continue, skipping" ;;
 | 
			
		||||
    i) COPY_INI=1           ; bugout "Archive INI/JSON/YML files" ;;
 | 
			
		||||
    h) EXIT_USAGE=1 ; break ;;
 | 
			
		||||
    l) LIMIT=$OPTARG        ; bugout "Limit to $LIMIT build(s)" ;;
 | 
			
		||||
  d|v) DEBUG=1              ; bugout "Debug ON" ;;
 | 
			
		||||
    n) DRYRUN=1             ; bugout "Dry Run" ;;
 | 
			
		||||
    -) IFS="=" read -r ONAM OVAL <<< "$OPTARG"
 | 
			
		||||
       case "$ONAM" in
 | 
			
		||||
       branch) BRANCH=$OVAL       ; bugout "Branch: $BRANCH" ;;
 | 
			
		||||
       resume) FIRST_CONF="$OVAL" ; bugout "Resume: $FIRST_CONF" ;;
 | 
			
		||||
     continue) CONTINUE=1   ; bugout "Continue" ;;
 | 
			
		||||
         skip) CONTSKIP=2   ; bugout "Continue, skipping" ;;
 | 
			
		||||
        limit) LIMIT=$OVAL  ; bugout "Limit to $LIMIT build(s)" ;;
 | 
			
		||||
          ini) COPY_INI=1   ; bugout "Archive INI/JSON/YML files" ;;
 | 
			
		||||
         help) [[ -z "$OVAL" ]] || perror "option can't take value $OVAL" $ONAM ; EXIT_USAGE=1 ;;
 | 
			
		||||
        debug) DEBUG=1      ; bugout "Debug ON" ;;
 | 
			
		||||
      nobuild) DRYRUN=1     ; bugout "Dry Run" ;;
 | 
			
		||||
            *) EXIT_USAGE=2 ; echo "$SELF: unrecognized option \`--$ONAM'" ; break ;;
 | 
			
		||||
       esac
 | 
			
		||||
       ;;
 | 
			
		||||
    *) EXIT_USAGE=2 ; break ;;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Extra arguments count as BRANCH, FIRST_CONF
 | 
			
		||||
shift $((OPTIND - 1))
 | 
			
		||||
[[ $# > 0 ]] && { BRANCH=$1 ; shift 1 ; bugout "BRANCH=$BRANCH" ; }
 | 
			
		||||
[[ $# > 0 ]] && { FIRST_CONF=$1 ; shift 1 ; bugout "FIRST_CONF=$FIRST_CONF" ; }
 | 
			
		||||
[[ $# > 0 ]] && { EXIT_USAGE=2 ; echo "too many arguments" ; }
 | 
			
		||||
 | 
			
		||||
((EXIT_USAGE)) && { usage ; let EXIT_USAGE-- ; exit $EXIT_USAGE ; }
 | 
			
		||||
 | 
			
		||||
echo "This script downloads each Configuration and attempts to build it."
 | 
			
		||||
echo "On failure the last-built configs will be left in your working copy."
 | 
			
		||||
echo "Restore your configs with 'git checkout -f' or 'git reset --hard HEAD'."
 | 
			
		||||
 | 
			
		||||
if [[ -f "$STAT_FILE" ]]; then
 | 
			
		||||
  IFS='*' read BRANCH FIRST_CONF <"$STAT_FILE"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# If -c is given start from the last attempted build
 | 
			
		||||
if ((CONTINUE)); then
 | 
			
		||||
  if [[ -z $BRANCH || -z $FIRST_CONF ]]; then
 | 
			
		||||
    echo "Nothing to continue"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
elif ((CONTSKIP)); then
 | 
			
		||||
  if [[ -n $BRANCH && -n $FIRST_CONF ]]; then
 | 
			
		||||
    SKIP_CONF=1
 | 
			
		||||
  else
 | 
			
		||||
    echo "Nothing to skip"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Check if the current repository has unmerged changes
 | 
			
		||||
if [[ $SKIP_CONF ]]; then
 | 
			
		||||
  echo "Skipping $FIRST_CONF"
 | 
			
		||||
elif [[ $FIRST_CONF ]]; then
 | 
			
		||||
  echo "Resuming from $FIRST_CONF"
 | 
			
		||||
else
 | 
			
		||||
  git diff --quiet || { echo "The working copy is modified. Commit or stash changes before proceeding."; exit ; }
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Create a temporary folder inside .pio
 | 
			
		||||
TMP=./.pio/build-$BRANCH
 | 
			
		||||
[[ -d "$TMP" ]] || mkdir -p $TMP
 | 
			
		||||
 | 
			
		||||
# Download Configurations into the temporary folder
 | 
			
		||||
if [[ ! -e "$TMP/README.md" ]]; then
 | 
			
		||||
  echo "Fetching Configurations from GitHub to $TMP"
 | 
			
		||||
  git clone --depth=1 --single-branch --branch "$BRANCH" $GITREPO "$TMP" || { echo "Failed to clone the configuration repository"; exit ; }
 | 
			
		||||
else
 | 
			
		||||
  echo "Using cached Configurations at $TMP"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo -e "Start build...\n====================="
 | 
			
		||||
shopt -s nullglob
 | 
			
		||||
IFS='
 | 
			
		||||
'
 | 
			
		||||
CONF_TREE=$( ls -d "$TMP"/config/examples/*/ "$TMP"/config/examples/*/*/ "$TMP"/config/examples/*/*/*/ "$TMP"/config/examples/*/*/*/*/ | grep -vE ".+\.(\w+)$" )
 | 
			
		||||
for CONF in $CONF_TREE ; do
 | 
			
		||||
 | 
			
		||||
  # Get a config's directory name
 | 
			
		||||
  DIR=$( echo $CONF | sed "s|$TMP/config/examples/||" )
 | 
			
		||||
 | 
			
		||||
  # If looking for a config, skip others
 | 
			
		||||
  [[ $FIRST_CONF ]] && [[ $FIRST_CONF != $DIR && "$FIRST_CONF/" != $DIR ]] && continue
 | 
			
		||||
  # Once found, stop looking
 | 
			
		||||
  unset FIRST_CONF
 | 
			
		||||
 | 
			
		||||
  # If skipping, don't build the found one
 | 
			
		||||
  [[ $SKIP_CONF ]] && { unset SKIP_CONF ; continue ; }
 | 
			
		||||
 | 
			
		||||
  # ...if skipping, don't build this one
 | 
			
		||||
  compgen -G "${CONF}Con*.h" > /dev/null || continue
 | 
			
		||||
 | 
			
		||||
  # Build or print build command for --nobuild
 | 
			
		||||
  if [[ $DRYRUN ]]; then
 | 
			
		||||
    echo -e "\033[0;32m[DRYRUN] build_example internal \"$TMP\" \"$DIR\"\033[0m"
 | 
			
		||||
  else
 | 
			
		||||
    # Remember where we are in case of failure
 | 
			
		||||
    echo "${BRANCH}*${DIR}" >"$STAT_FILE"
 | 
			
		||||
    # Build folder is unknown so delete all report files
 | 
			
		||||
    if [[ $COPY_INI ]]; then
 | 
			
		||||
      IFIND='find ./.pio/build/ -name "config.ini" -o -name "schema.json" -o -name "schema.yml"'
 | 
			
		||||
      $IFIND -exec rm "{}" \;
 | 
			
		||||
    fi
 | 
			
		||||
    ((DEBUG)) && echo "\"$HERE/build_example\" internal \"$TMP\" \"$DIR\""
 | 
			
		||||
    "$HERE/build_example" internal "$TMP" "$DIR" || { echo "Failed to build $DIR"; exit ; }
 | 
			
		||||
    # Build folder is unknown so copy all report files
 | 
			
		||||
    [[ $COPY_INI ]] && $IFIND -exec cp "{}" "$CONF" \;
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  ((--LIMIT)) || { echo "Limit reached" ; PAUSE=1 ; break ; }
 | 
			
		||||
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Delete the build state if not paused early
 | 
			
		||||
[[ $PAUSE ]] || rm "$STAT_FILE"
 | 
			
		||||
 | 
			
		||||
# Delete the temp folder if not preserving generated INI files
 | 
			
		||||
if [[ -e "$TMP/config/examples" ]]; then
 | 
			
		||||
  if [[ $COPY_INI ]]; then
 | 
			
		||||
    OPEN=$( which gnome-open xdg-open open | head -n1 )
 | 
			
		||||
    $OPEN "$TMP"
 | 
			
		||||
  elif [[ ! $PAUSE ]]; then
 | 
			
		||||
    rm -rf "$TMP"
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
							
								
								
									
										38
									
								
								buildroot/bin/build_example
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										38
									
								
								buildroot/bin/build_example
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
#
 | 
			
		||||
# build_example
 | 
			
		||||
#
 | 
			
		||||
# Usage: build_example internal config-home config-folder
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
. mfutil
 | 
			
		||||
 | 
			
		||||
# Require 'internal' as the first argument
 | 
			
		||||
[[ "$1" == "internal" ]] || { echo "Don't call this script directly, use build_all_examples instead." ; exit 1 ; }
 | 
			
		||||
 | 
			
		||||
echo "Testing $3:"
 | 
			
		||||
 | 
			
		||||
SUB=$2/config/examples/$3
 | 
			
		||||
[[ -d "$SUB" ]] || { echo "$SUB is not a good path" ; exit 1 ; }
 | 
			
		||||
 | 
			
		||||
compgen -G "${SUB}Con*.h" > /dev/null || { echo "No configuration files found in $SUB" ; exit 1 ; }
 | 
			
		||||
 | 
			
		||||
echo "Getting configuration files from $SUB"
 | 
			
		||||
cp "$2/config/default"/*.h    Marlin/
 | 
			
		||||
cp "$SUB"/Configuration.h     Marlin/ 2>/dev/null
 | 
			
		||||
cp "$SUB"/Configuration_adv.h Marlin/ 2>/dev/null
 | 
			
		||||
cp "$SUB"/_Bootscreen.h       Marlin/ 2>/dev/null
 | 
			
		||||
cp "$SUB"/_Statusscreen.h     Marlin/ 2>/dev/null
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
# Strip #error lines from Configuration.h
 | 
			
		||||
IFS=$'\n'; set -f
 | 
			
		||||
$SED -i~ -e "20,30{/#error/d}" Marlin/Configuration.h
 | 
			
		||||
rm Marlin/Configuration.h~
 | 
			
		||||
unset IFS; set +f
 | 
			
		||||
 | 
			
		||||
echo "Building the firmware now..."
 | 
			
		||||
$HERE/mftest -s -a -n1 || { echo "Failed"; exit 1; }
 | 
			
		||||
 | 
			
		||||
echo "Success"
 | 
			
		||||
							
								
								
									
										14
									
								
								buildroot/bin/ci_src_filter
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										14
									
								
								buildroot/bin/ci_src_filter
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# exit on first failure
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
SED=$(which gsed sed | head -n1)
 | 
			
		||||
FN="platformio.ini"
 | 
			
		||||
 | 
			
		||||
if [[ $1 == "-n" ]]; then
 | 
			
		||||
  "${SED}" -i "s/default_src_filter/org_src_filter/" $FN
 | 
			
		||||
  "${SED}" -i "/org_src_filter/ s/^/default_src_filter = +<src\/*>\n/" $FN
 | 
			
		||||
else
 | 
			
		||||
  git checkout $FN 2>/dev/null
 | 
			
		||||
fi
 | 
			
		||||
@@ -4,47 +4,35 @@
 | 
			
		||||
#
 | 
			
		||||
# Make a Version.h file to accompany CUSTOM_VERSION_FILE
 | 
			
		||||
#
 | 
			
		||||
# Authors: jbrazio, thinkyhead, InsanityAutomation, rfinnie
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DIR=${1:-"Marlin"}
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
# MRCC3=$( git merge-base HEAD upstream/bugfix-2.0.x 2>/dev/null )
 | 
			
		||||
# MRCC2=$( git merge-base HEAD upstream/bugfix-1.1.x 2>/dev/null )
 | 
			
		||||
# MRCC1=$( git merge-base HEAD upstream/1.1.x 2>/dev/null )
 | 
			
		||||
DIR="${1:-Marlin}"
 | 
			
		||||
READ_FILE="${READ_FILE:-${DIR}/Version.h}"
 | 
			
		||||
WRITE_FILE="${WRITE_FILE:-${READ_FILE}}"
 | 
			
		||||
 | 
			
		||||
# BASE='?'
 | 
			
		||||
# if [[ -n $MRCC3 && $MRCC3 != $MRCC2 ]]; then
 | 
			
		||||
#   BASE=bugfix-2.0.x
 | 
			
		||||
# elif [[ -n $MRCC2 ]]; then
 | 
			
		||||
#   BASE=bugfix-1.1.x
 | 
			
		||||
# elif [[ -n $MRCC1 ]]; then
 | 
			
		||||
#   BASE=1.1.x
 | 
			
		||||
# fi
 | 
			
		||||
BRANCH="$(git -C "${DIR}" symbolic-ref -q --short HEAD 2>/dev/null || true)"
 | 
			
		||||
VERSION="$(git -C "${DIR}" describe --tags --first-parent 2>/dev/null || true)"
 | 
			
		||||
 | 
			
		||||
BUILDATE=$(date '+%s')
 | 
			
		||||
DISTDATE=$(date '+%Y-%m-%d %H:%M')
 | 
			
		||||
 | 
			
		||||
BRANCH=$(git -C "${DIR}" symbolic-ref -q --short HEAD)
 | 
			
		||||
VERSION=$(git -C "${DIR}" describe --tags --first-parent 2>/dev/null)
 | 
			
		||||
 | 
			
		||||
[ -z "${BRANCH}" ] && BRANCH=$(echo "${TRAVIS_BRANCH}")
 | 
			
		||||
[ -z "${VERSION}" ] && VERSION=$(git -C "${DIR}" describe --tags --first-parent --always 2>/dev/null)
 | 
			
		||||
 | 
			
		||||
SHORT_BUILD_VERSION=$(echo "${BRANCH}")
 | 
			
		||||
DETAILED_BUILD_VERSION=$(echo "${BRANCH}-${VERSION}")
 | 
			
		||||
STRING_DISTRIBUTION_DATE="${STRING_DISTRIBUTION_DATE:-$(date '+%Y-%m-%d %H:%M')}"
 | 
			
		||||
SHORT_BUILD_VERSION="${SHORT_BUILD_VERSION:-${BRANCH}}"
 | 
			
		||||
DETAILED_BUILD_VERSION="${DETAILED_BUILD_VERSION:-${BRANCH}-${VERSION}}"
 | 
			
		||||
 | 
			
		||||
# Gets some misc options from their defaults
 | 
			
		||||
DEFAULT_MACHINE_UUID=$(awk -F'"' \
 | 
			
		||||
  '/#define DEFAULT_MACHINE_UUID/{ print $2 }' < "${DIR}/Version.h")
 | 
			
		||||
MACHINE_NAME=$(awk -F'"' \
 | 
			
		||||
  '/#define MACHINE_NAME/{ print $2 }' < "${DIR}/Version.h")
 | 
			
		||||
PROTOCOL_VERSION=$(awk -F'"' \
 | 
			
		||||
  '/#define PROTOCOL_VERSION/{ print $2 }' < "${DIR}/Version.h")
 | 
			
		||||
SOURCE_CODE_URL=$(awk -F'"' \
 | 
			
		||||
  '/#define SOURCE_CODE_URL/{ print $2 }' < "${DIR}/Version.h")
 | 
			
		||||
WEBSITE_URL=$(awk -F'"' \
 | 
			
		||||
  '/#define WEBSITE_URL/{ print $2 }' < "${DIR}/Version.h")
 | 
			
		||||
DEFAULT_MACHINE_UUID="${DEFAULT_MACHINE_UUID:-$(awk -F'"' \
 | 
			
		||||
  '/#define DEFAULT_MACHINE_UUID/{ print $2 }' < "${READ_FILE}")}"
 | 
			
		||||
MACHINE_NAME="${MACHINE_NAME:-$(awk -F'"' \
 | 
			
		||||
  '/#define MACHINE_NAME/{ print $2 }' < "${READ_FILE}")}"
 | 
			
		||||
PROTOCOL_VERSION="${PROTOCOL_VERSION:-$(awk -F'"' \
 | 
			
		||||
  '/#define PROTOCOL_VERSION/{ print $2 }' < "${READ_FILE}")}"
 | 
			
		||||
SOURCE_CODE_URL="${SOURCE_CODE_URL:-$(awk -F'"' \
 | 
			
		||||
  '/#define SOURCE_CODE_URL/{ print $2 }' < "${READ_FILE}")}"
 | 
			
		||||
WEBSITE_URL="${WEBSITE_URL:-$(awk -F'"' \
 | 
			
		||||
  '/#define WEBSITE_URL/{ print $2 }' < "${READ_FILE}")}"
 | 
			
		||||
 | 
			
		||||
cat > "${DIR}/Version.h" <<EOF
 | 
			
		||||
cat > "${WRITE_FILE}" <<EOF
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
 | 
			
		||||
@@ -97,7 +85,7 @@ cat > "${DIR}/Version.h" <<EOF
 | 
			
		||||
  * version was tagged.
 | 
			
		||||
  */
 | 
			
		||||
#ifndef STRING_DISTRIBUTION_DATE
 | 
			
		||||
  #define STRING_DISTRIBUTION_DATE "${DISTDATE}"
 | 
			
		||||
  #define STRING_DISTRIBUTION_DATE "${STRING_DISTRIBUTION_DATE}"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										338
									
								
								buildroot/bin/mftest
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										338
									
								
								buildroot/bin/mftest
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,338 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
#
 | 
			
		||||
#  mftest                             Select a test to apply and build
 | 
			
		||||
#  mftest -b [#]                      Build the auto-detected environment
 | 
			
		||||
#  mftest -u [#]                      Upload the auto-detected environment
 | 
			
		||||
#  mftest -tname -n# [-y]             Set config options and optionally build a test
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
[[ -d Marlin/src ]] || { echo "Please 'cd' to the Marlin repo root." ; exit 1 ; }
 | 
			
		||||
 | 
			
		||||
perror() { echo -e "$0: \033[0;31m$1 -- $2\033[0m" ; }
 | 
			
		||||
errout() { echo -e "\033[0;31m$1\033[0m" ; }
 | 
			
		||||
bugout() { ((DEBUG)) && echo -e "\033[0;32m$1\033[0m" ; }
 | 
			
		||||
 | 
			
		||||
usage() {
 | 
			
		||||
  echo "
 | 
			
		||||
Usage: mftest [-t|--env=<env|index>] [-n|--num=<num>] [-m|--make] [-y|--build=<Y|n>]
 | 
			
		||||
       mftest [-a|--autobuild]
 | 
			
		||||
       mftest [-r|--rebuild]
 | 
			
		||||
       mftest [-s|--silent]
 | 
			
		||||
       mftest [-u|--autoupload] [-n|--num=<num>]
 | 
			
		||||
 | 
			
		||||
OPTIONS
 | 
			
		||||
  -t --env         The environment to apply / run, or the menu index number.
 | 
			
		||||
  -n --num         The index of the test to run. (In file order.)
 | 
			
		||||
  -m --make        Use the make / Docker method for the build.
 | 
			
		||||
  -y --build       Skip 'Do you want to build this test?' and assume YES.
 | 
			
		||||
  -h --help        Print this help.
 | 
			
		||||
  -a --autobuild   PIO Build using the MOTHERBOARD environment.
 | 
			
		||||
  -u --autoupload  PIO Upload using the MOTHERBOARD environment.
 | 
			
		||||
  -v --verbose     Extra output for debugging.
 | 
			
		||||
  -s --silent      Silence build output from PlatformIO.
 | 
			
		||||
  -d --default     Restore to defaults before applying configs.
 | 
			
		||||
 | 
			
		||||
env shortcuts: tree due esp lin lp8|lpc8 lp9|lpc9 m128 m256|mega stm|f1 f4 f7 s6 teensy|t31|t32 t35|t36 t40|t41
 | 
			
		||||
"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TESTPATH=buildroot/tests
 | 
			
		||||
 | 
			
		||||
STATE_FILE="./.pio/.mftestrc"
 | 
			
		||||
SED=$(which gsed sed | head -n1)
 | 
			
		||||
 | 
			
		||||
shopt -s extglob nocasematch
 | 
			
		||||
 | 
			
		||||
# Matching patterns
 | 
			
		||||
ISNUM='^[0-9]+$'
 | 
			
		||||
ISRST='^(restore)_'
 | 
			
		||||
ISCMD='^(restore|opt|exec|use|pins|env)_'
 | 
			
		||||
ISEXEC='^exec_'
 | 
			
		||||
ISCONT='\\ *$'
 | 
			
		||||
 | 
			
		||||
# Get environment, test number, etc. from the command
 | 
			
		||||
TESTENV='-'
 | 
			
		||||
CHOICE=0
 | 
			
		||||
DEBUG=0
 | 
			
		||||
 | 
			
		||||
while getopts 'abdhmrsuvyn:t:-:' OFLAG; do
 | 
			
		||||
  case "${OFLAG}" in
 | 
			
		||||
    a) AUTO_BUILD=1 ; bugout "Auto-Build target..." ;;
 | 
			
		||||
    d) DL_DEFAULTS=1 ; bugout "Restore to defaults..." ;;
 | 
			
		||||
    h) EXIT_USAGE=1 ;;
 | 
			
		||||
    m) USE_MAKE=1 ; bugout "Using make with Docker..." ;;
 | 
			
		||||
    n) case "$OPTARG" in
 | 
			
		||||
         *[!0-9]*) perror "option requires a number" $OFLAG ; EXIT_USAGE=2 ;;
 | 
			
		||||
                *) CHOICE="$OPTARG" ; bugout "Got a number: $CHOICE" ;;
 | 
			
		||||
       esac
 | 
			
		||||
       ;;
 | 
			
		||||
    r) REBUILD=1         ; bugout "Rebuilding previous..." ;;
 | 
			
		||||
    s) SILENT_FLAG="-s" ;;
 | 
			
		||||
    t) TESTENV="$OPTARG" ; bugout "Got a target: $TESTENV" ;;
 | 
			
		||||
    u) AUTO_BUILD=2      ; bugout "Auto-Upload target..." ;;
 | 
			
		||||
    v) DEBUG=1           ; bugout "Debug ON" ;;
 | 
			
		||||
    y) BUILD_YES='Y'     ; bugout "Build will initiate..." ;;
 | 
			
		||||
    -) IFS="=" read -r ONAM OVAL <<< "$OPTARG"
 | 
			
		||||
       case "$ONAM" in
 | 
			
		||||
         help) [[ -z "$OVAL" ]] || perror "option can't take value $OVAL" $ONAM ; EXIT_USAGE=1 ;;
 | 
			
		||||
    autobuild) AUTO_BUILD=1 ; bugout "Auto-Build target..."  ;;
 | 
			
		||||
   autoupload) AUTO_BUILD=2 ; bugout "Auto-Upload target..." ;;
 | 
			
		||||
          env) case "$OVAL" in
 | 
			
		||||
                 '') perror "option requires a value" $ONAM ; EXIT_USAGE=2 ;;
 | 
			
		||||
                  *) TESTENV="$OVAL" ; bugout "Got a target: $TESTENV" ;;
 | 
			
		||||
               esac
 | 
			
		||||
               ;;
 | 
			
		||||
          num) case "$OVAL" in
 | 
			
		||||
                 [0-9]+) CHOICE="$OVAL" ; bugout "Got a number: $CHOICE" ;;
 | 
			
		||||
                      *) perror "option requires a value" $ONAM ; EXIT_USAGE=2 ;;
 | 
			
		||||
               esac
 | 
			
		||||
               ;;
 | 
			
		||||
      rebuild) REBUILD=1  ; bugout "Rebuilding previous..." ;;
 | 
			
		||||
       silent) SILENT_FLAG="-s" ;;
 | 
			
		||||
         make) USE_MAKE=1 ; bugout "Using make with Docker..." ;;
 | 
			
		||||
debug|verbose) DEBUG=1    ; bugout "Debug ON" ;;
 | 
			
		||||
      default) DL_DEFAULTS=1 ; bugout "Restore to defaults..." ;;
 | 
			
		||||
        build) case "$OVAL" in
 | 
			
		||||
                 ''|y|yes) BUILD_YES='Y' ;;
 | 
			
		||||
                     n|no) BUILD_YES='N' ;;
 | 
			
		||||
                        *) perror "option value must be y, n, yes, or no" $ONAM ; EXIT_USAGE=2 ;;
 | 
			
		||||
               esac
 | 
			
		||||
               bugout "Build will initiate? ($BUILD_YES)"
 | 
			
		||||
               ;;
 | 
			
		||||
            *) perror "Unknown flag" "$OPTARG" ; EXIT_USAGE=2 ;;
 | 
			
		||||
       esac
 | 
			
		||||
       ;;
 | 
			
		||||
    *) EXIT_USAGE=2 ;;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
((EXIT_USAGE)) && { usage ; let EXIT_USAGE-- ; exit $EXIT_USAGE ; }
 | 
			
		||||
 | 
			
		||||
if ((REBUILD)); then
 | 
			
		||||
  bugout "Rebuilding previous..."
 | 
			
		||||
  # Build with the last-built env
 | 
			
		||||
  [[ -f "$STATE_FILE" ]] || { errout "No previous (-r) build state found." ; exit 1 ; }
 | 
			
		||||
  read TESTENV <"$STATE_FILE"
 | 
			
		||||
  pio run $SILENT_FLAG -d . -e $TESTENV
 | 
			
		||||
  exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
case $TESTENV in
 | 
			
		||||
    tree) pio run -d . -e include_tree ; exit 1 ;;
 | 
			
		||||
     due) TESTENV='DUE' ;;
 | 
			
		||||
     esp) TESTENV='esp32' ;;
 | 
			
		||||
    lin*) TESTENV='linux_native' ;;
 | 
			
		||||
lp8|lpc8) TESTENV='LPC1768' ;;
 | 
			
		||||
lp9|lpc9) TESTENV='LPC1769' ;;
 | 
			
		||||
    m128) TESTENV='mega1280' ;;
 | 
			
		||||
    m256) TESTENV='mega2560' ;;
 | 
			
		||||
    mega) TESTENV='mega2560' ;;
 | 
			
		||||
     stm) TESTENV='STM32F103RE' ;;
 | 
			
		||||
      f1) TESTENV='STM32F103RE' ;;
 | 
			
		||||
      f4) TESTENV='STM32F4' ;;
 | 
			
		||||
      f7) TESTENV='STM32F7' ;;
 | 
			
		||||
      s6) TESTENV='FYSETC_S6' ;;
 | 
			
		||||
  teensy) TESTENV='teensy31' ;;
 | 
			
		||||
     t31) TESTENV='teensy31' ;;
 | 
			
		||||
     t32) TESTENV='teensy31' ;;
 | 
			
		||||
     t35) TESTENV='teensy35' ;;
 | 
			
		||||
     t36) TESTENV='teensy35' ;;
 | 
			
		||||
     t40) TESTENV='teensy41' ;;
 | 
			
		||||
     t41) TESTENV='teensy41' ;;
 | 
			
		||||
[1-9]|[1-9][0-9]) TESTNUM=$TESTENV ; TESTENV=- ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
if ((AUTO_BUILD)); then
 | 
			
		||||
  #
 | 
			
		||||
  # List environments that apply to the current MOTHERBOARD.
 | 
			
		||||
  #
 | 
			
		||||
  case $(uname | tr '[:upper:]' '[:lower:]') in
 | 
			
		||||
    darwin) SYS='mac' ;;
 | 
			
		||||
    *linux) SYS='lin' ;;
 | 
			
		||||
      win*) SYS='win' ;;
 | 
			
		||||
     msys*) SYS='win' ;;
 | 
			
		||||
   cygwin*) SYS='win' ;;
 | 
			
		||||
    mingw*) SYS='win' ;;
 | 
			
		||||
         *) SYS='uni' ;;
 | 
			
		||||
  esac
 | 
			
		||||
  echo ; echo -n "Auto " ; ((AUTO_BUILD == 2)) && echo "Upload..." || echo "Build..."
 | 
			
		||||
  MB=$( grep -E "^\s*#define MOTHERBOARD" Marlin/Configuration.h | awk '{ print $3 }' | $SED 's/BOARD_//;s/\r//' )
 | 
			
		||||
  [[ -z $MB ]] && { echo "Error - Can't read MOTHERBOARD setting." ; exit 1 ; }
 | 
			
		||||
  BLINE=$( grep -E "define\s+BOARD_$MB\b" Marlin/src/core/boards.h )
 | 
			
		||||
  BNUM=$( $SED -E 's/^.+BOARD_[^ ]+ +([0-9]+).+$/\1/' <<<"$BLINE" )
 | 
			
		||||
  BDESC=$( $SED -E 's/^.+\/\/ *(.+)$/\1/' <<<"$BLINE" )
 | 
			
		||||
  [[ -z $BNUM ]] && { echo "Error - Can't find BOARD_$MB in core/boards.h." ; exit 1 ; }
 | 
			
		||||
  ENVS=( $( grep -EA1 "MB\(.*\b$MB\b.*\)" Marlin/src/pins/pins.h | grep -E "#include.+//.+(env|$SYS):[^ ]+" | grep -oE "(env|$SYS):[^ ]+" | $SED -E "s/(env|$SYS)://" ) )
 | 
			
		||||
  [[ -z $ENVS ]] && { errout "Error - Can't find target(s) for $MB ($BNUM)." ; exit 1 ; }
 | 
			
		||||
  ECOUNT=${#ENVS[*]}
 | 
			
		||||
 | 
			
		||||
  if [[ $ECOUNT == 1 ]]; then
 | 
			
		||||
    TARGET=$ENVS
 | 
			
		||||
  else
 | 
			
		||||
    if [[ $CHOICE == 0 ]]; then
 | 
			
		||||
      # List env names and numbers. Get selection.
 | 
			
		||||
      echo "Available targets for \"$BDESC\" | $MB ($BNUM):"
 | 
			
		||||
 | 
			
		||||
      IND=0 ; for ENV in "${ENVS[@]}"; do let IND++ ; echo " $IND) $ENV" ; done
 | 
			
		||||
 | 
			
		||||
      if [[ $ECOUNT > 1 ]]; then
 | 
			
		||||
        for (( ; ; ))
 | 
			
		||||
        do
 | 
			
		||||
          read -p "Select a target for '$MB' (1-$ECOUNT) : " CHOICE
 | 
			
		||||
          [[ -z "$CHOICE" ]] && { echo '(canceled)' ; exit 1 ; }
 | 
			
		||||
          [[ $CHOICE =~ $ISNUM ]] && ((CHOICE >= 1 && CHOICE <= ECOUNT)) && break
 | 
			
		||||
          errout ">>> Invalid environment choice '$CHOICE'."
 | 
			
		||||
        done
 | 
			
		||||
        echo
 | 
			
		||||
      fi
 | 
			
		||||
    else
 | 
			
		||||
      echo "Detected \"$BDESC\" | $MB ($BNUM)."
 | 
			
		||||
      [[ $CHOICE > $ECOUNT ]] && { echo "Environment selection out of range." ; exit 1 ; }
 | 
			
		||||
    fi
 | 
			
		||||
    TARGET="${ENVS[$CHOICE-1]}"
 | 
			
		||||
    echo "Selected $TARGET"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  echo "$TARGET" >"$STATE_FILE"
 | 
			
		||||
 | 
			
		||||
  if ((AUTO_BUILD == 2)); then
 | 
			
		||||
    echo "Uploading environment $TARGET for board $MB ($BNUM)..." ; echo
 | 
			
		||||
    pio run $SILENT_FLAG -t upload -e $TARGET
 | 
			
		||||
  else
 | 
			
		||||
    echo "Building environment $TARGET for board $MB ($BNUM)..." ; echo
 | 
			
		||||
    pio run $SILENT_FLAG -e $TARGET
 | 
			
		||||
  fi
 | 
			
		||||
  exit $?
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# List available tests and ask for selection
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
if [[ $TESTENV == '-' ]]; then
 | 
			
		||||
  IND=0
 | 
			
		||||
  NAMES=()
 | 
			
		||||
  MENU=()
 | 
			
		||||
  BIGLEN=0
 | 
			
		||||
  for FILE in $( ls -1 $TESTPATH/* | sort -f )
 | 
			
		||||
  do
 | 
			
		||||
    let IND++
 | 
			
		||||
    TNAME=${FILE/$TESTPATH\//}
 | 
			
		||||
    NAMES+=($TNAME)
 | 
			
		||||
    IFS=""
 | 
			
		||||
    ITEM=$( printf "%2i) %s" $IND $TNAME )
 | 
			
		||||
    MENU+=($ITEM)
 | 
			
		||||
    [[ ${#ITEM} -gt $BIGLEN ]] && BIGLEN=${#ITEM}
 | 
			
		||||
  done
 | 
			
		||||
 | 
			
		||||
  (( BIGLEN += 2 ))
 | 
			
		||||
  THIRD=$(( (${#MENU[@]} + 2) / 3 ))
 | 
			
		||||
  for ((i = 0; i < $THIRD; i++))
 | 
			
		||||
  do
 | 
			
		||||
    COL1=$i ; COL2=$(( $i + $THIRD )) ; COL3=$(( $i + 2 * $THIRD ))
 | 
			
		||||
    FMT="%-${BIGLEN}s"
 | 
			
		||||
    printf "${FMT}${FMT}${FMT}\n" ${MENU[$COL1]} ${MENU[$COL2]} ${MENU[$COL3]}
 | 
			
		||||
  done
 | 
			
		||||
 | 
			
		||||
  echo
 | 
			
		||||
  for (( ; ; ))
 | 
			
		||||
  do
 | 
			
		||||
    if [[ $TESTNUM -gt 0 ]]; then
 | 
			
		||||
      NAMEIND=$TESTNUM
 | 
			
		||||
    else
 | 
			
		||||
      read -p "Select a test to apply (1-$IND) : " NAMEIND
 | 
			
		||||
    fi
 | 
			
		||||
    [[ -z $NAMEIND ]] && { errout "(canceled)" ; exit 1 ; }
 | 
			
		||||
    TESTENV=${NAMES[$NAMEIND-1]}
 | 
			
		||||
    [[ $TESTNUM -gt 0 ]] && { echo "Preselected test $TESTNUM ... ($TESTENV)" ; TESTNUM='' ; }
 | 
			
		||||
    [[ $NAMEIND =~ $ISNUM ]] && ((NAMEIND >= 1 && NAMEIND <= IND)) && { TESTENV=${NAMES[$NAMEIND-1]} ; echo ; break ; }
 | 
			
		||||
    errout "Invalid selection."
 | 
			
		||||
  done
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Get the contents of the test file
 | 
			
		||||
OUT=$( cat $TESTPATH/$TESTENV 2>/dev/null ) || { errout "Can't find test '$TESTENV'." ; exit 1 ; }
 | 
			
		||||
 | 
			
		||||
# Count up the number of tests
 | 
			
		||||
TESTCOUNT=$( awk "/$ISEXEC/{a++}END{print a}" <<<"$OUT" )
 | 
			
		||||
 | 
			
		||||
# User entered a number?
 | 
			
		||||
(( CHOICE && CHOICE > TESTCOUNT )) && { errout "Invalid test selection '$CHOICE' (1-$TESTCOUNT)." ; exit 1 ; }
 | 
			
		||||
 | 
			
		||||
if [[ $CHOICE == 0 ]]; then
 | 
			
		||||
  #
 | 
			
		||||
  # List test descriptions with numbers and get selection
 | 
			
		||||
  #
 | 
			
		||||
  echo "Available '$TESTENV' tests:" ; echo "$OUT" | {
 | 
			
		||||
    IND=0
 | 
			
		||||
    while IFS= read -r LINE
 | 
			
		||||
    do
 | 
			
		||||
      if [[ $LINE =~ $ISEXEC ]]; then
 | 
			
		||||
        DESC=$( "$SED" -E 's/^exec_test \$1 \$2 "([^"]+)".*$/\1/g' <<<"$LINE" )
 | 
			
		||||
        (( ++IND < 10 )) && echo -n " "
 | 
			
		||||
        echo " $IND) $DESC"
 | 
			
		||||
      fi
 | 
			
		||||
    done
 | 
			
		||||
  }
 | 
			
		||||
  CHOICE=1
 | 
			
		||||
  if [[ $TESTCOUNT > 1 ]]; then
 | 
			
		||||
    for (( ; ; ))
 | 
			
		||||
    do
 | 
			
		||||
      read -p "Select a '$TESTENV' test (1-$TESTCOUNT) : " CHOICE
 | 
			
		||||
      [[ -z "$CHOICE" ]] && { errout "(canceled)" ; exit 1 ; }
 | 
			
		||||
      [[ $CHOICE =~ $ISNUM ]] && ((CHOICE >= 1 && CHOICE <= TESTCOUNT)) && break
 | 
			
		||||
      errout ">>> Invalid test selection '$CHOICE'."
 | 
			
		||||
    done
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Restore to defaults if requested
 | 
			
		||||
#
 | 
			
		||||
((DL_DEFAULTS)) && use_example_configs
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Run the specified test lines
 | 
			
		||||
#
 | 
			
		||||
echo -ne "\033[0;33m"
 | 
			
		||||
echo "$OUT" | {
 | 
			
		||||
  IND=0
 | 
			
		||||
  GOTX=0
 | 
			
		||||
  CMD=""
 | 
			
		||||
  while IFS= read -r LINE
 | 
			
		||||
  do
 | 
			
		||||
    if [[ $LINE =~ $ISCMD || $GOTX == 1 ]]; then
 | 
			
		||||
      ((!IND)) && let IND++
 | 
			
		||||
      if [[ $LINE =~ $ISEXEC ]]; then
 | 
			
		||||
        ((IND++ > CHOICE)) && break
 | 
			
		||||
      else
 | 
			
		||||
        ((!HEADER)) && {
 | 
			
		||||
          HEADER=1
 | 
			
		||||
          echo -e "\n#\n# Test $TESTENV ($CHOICE) $DESC\n#"
 | 
			
		||||
        }
 | 
			
		||||
        ((IND == CHOICE)) && {
 | 
			
		||||
          GOTX=1
 | 
			
		||||
          [[ -n $DL_DEFAULTS && $LINE =~ $ISRST ]] && LINE="use_example_configs"
 | 
			
		||||
          [[ $CMD == "" ]] && CMD="$LINE" || CMD=$( echo -e "$CMD$LINE" | $SED -e 's/\\//g' | $SED -E 's/ +/ /g' )
 | 
			
		||||
          [[ $LINE =~ $ISCONT ]] || { echo "$CMD" ; eval "$CMD" ; CMD="" ; }
 | 
			
		||||
        }
 | 
			
		||||
      fi
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
echo -ne "\033[0m"
 | 
			
		||||
 | 
			
		||||
# Make clear it's a TEST
 | 
			
		||||
opt_set CUSTOM_MACHINE_NAME "\"Test $TESTENV ($CHOICE)\""
 | 
			
		||||
 | 
			
		||||
# Build the test too?
 | 
			
		||||
if [[ -z "$BUILD_YES" ]]; then
 | 
			
		||||
  echo
 | 
			
		||||
  read -p "Build $TESTENV test #$CHOICE (y/N) ? " BUILD_YES
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
[[ $BUILD_YES == 'Y' || $BUILD_YES == 'Yes' ]] && {
 | 
			
		||||
  ((USE_MAKE)) && make tests-single-local TEST_TARGET=$TESTENV ONLY_TEST=$CHOICE
 | 
			
		||||
  ((USE_MAKE)) || pio run $SILENT_FLAG -d . -e $TESTENV
 | 
			
		||||
  echo "$TESTENV" >"$STATE_FILE"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								buildroot/bin/mfutil
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								buildroot/bin/mfutil
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
#
 | 
			
		||||
# mfutil - check env and define helpers
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# Check dependencies
 | 
			
		||||
which curl 1>/dev/null 2>&1 || { echo "curl not found! Please install it."; exit ; }
 | 
			
		||||
which git 1>/dev/null 2>&1 || { echo "git not found! Please install it."; exit ; }
 | 
			
		||||
 | 
			
		||||
SED=$(command -v gsed 2>/dev/null || command -v sed 2>/dev/null)
 | 
			
		||||
[[ -z "$SED" ]] && { echo "No sed found, please install sed" ; exit 1 ; }
 | 
			
		||||
 | 
			
		||||
OPEN=$( which gnome-open xdg-open open | head -n1 )
 | 
			
		||||
 | 
			
		||||
SELF=`basename "$0"`
 | 
			
		||||
HERE=`dirname "$0"`
 | 
			
		||||
 | 
			
		||||
# Check if called in the right location
 | 
			
		||||
[[ -e "Marlin/src" ]] || { echo -e "This script must be called from a Marlin working copy with:\n ./buildroot/bin/$SELF $1" ; exit ; }
 | 
			
		||||
 | 
			
		||||
perror() { echo -e "$0: \033[0;31m$1 -- $2\033[0m" ; }
 | 
			
		||||
bugout() { ((DEBUG)) && echo -e "\033[0;32m$1\033[0m" ; }
 | 
			
		||||
@@ -3,11 +3,13 @@
 | 
			
		||||
# exit on first failure
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
SED=$(which gsed || which sed)
 | 
			
		||||
SED=$(which gsed sed | head -n1)
 | 
			
		||||
 | 
			
		||||
for opt in "$@" ; do
 | 
			
		||||
  # Logic for returning nonzero based on answer here: https://stackoverflow.com/a/15966279/104648
 | 
			
		||||
  eval "${SED} -i '/\([[:blank:]]*\)\(\/\/\)*\([[:blank:]]*\)\(#define \b${opt}\b\)/{s//\1\3\/\/\4/;h};\${x;/./{x;q0};x;q9}' Marlin/Configuration.h" ||
 | 
			
		||||
  eval "${SED} -i '/\([[:blank:]]*\)\(\/\/\)*\([[:blank:]]*\)\(#define \b${opt}\b\)/{s//\1\3\/\/\4/;h};\${x;/./{x;q0};x;q9}' Marlin/Configuration_adv.h" ||
 | 
			
		||||
  (echo "ERROR: opt_disable Can't find ${opt}" >&2 && exit 9)
 | 
			
		||||
  DID=0 ; FOUND=0
 | 
			
		||||
  for FN in Configuration Configuration_adv; do
 | 
			
		||||
    "${SED}" -i "/^\(\s*\)\(#define\s\+${opt}\b\s\?\)\(\s\s\)\?/{s//\1\/\/\2/;h};\${x;/./{x;q0};x;q9}" Marlin/$FN.h && DID=1
 | 
			
		||||
    ((DID||FOUND)) || { grep -E "^\s*//\s*#define\s+${opt}\b" Marlin/$FN.h >/dev/null && FOUND=1 ; }
 | 
			
		||||
  done
 | 
			
		||||
  ((DID||FOUND)) || (echo "ERROR: $(basename $0) Can't find ${opt}" >&2 && exit 9)
 | 
			
		||||
done
 | 
			
		||||
 
 | 
			
		||||
@@ -3,11 +3,13 @@
 | 
			
		||||
# exit on first failure
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
SED=$(which gsed || which sed)
 | 
			
		||||
SED=$(which gsed sed | head -n1)
 | 
			
		||||
 | 
			
		||||
for opt in "$@" ; do
 | 
			
		||||
  # Logic for returning nonzero based on answer here: https://stackoverflow.com/a/15966279/104648
 | 
			
		||||
  eval "${SED} -i '/\(\/\/\)*[[:blank:]]*\(#define \b${opt}\b\)/{s//\2/;h};\${x;/./{x;q0};x;q9}' Marlin/Configuration.h" ||
 | 
			
		||||
  eval "${SED} -i '/\(\/\/\)*[[:blank:]]*\(#define \b${opt}\b\)/{s//\2/;h};\${x;/./{x;q0};x;q9}' Marlin/Configuration_adv.h" ||
 | 
			
		||||
  (echo "ERROR: opt_enable Can't find ${opt}" >&2 && exit 9)
 | 
			
		||||
  DID=0 ; FOUND=0
 | 
			
		||||
  for FN in Configuration Configuration_adv; do
 | 
			
		||||
    "${SED}" -i "/^\(\s*\)\/\/\(\s*\)\(#define\s\+${opt}\b\)\( \?\)/{s//\1\2\3\4\4\4/;h};\${x;/./{x;q0};x;q9}" Marlin/$FN.h && DID=1
 | 
			
		||||
    ((DID||FOUND)) || { grep -E "^\s*#define\s+${opt}\b" Marlin/$FN.h >/dev/null && FOUND=1 ; }
 | 
			
		||||
  done
 | 
			
		||||
  ((DID||FOUND)) || (echo "ERROR: $(basename $0) Can't find ${opt}" >&2 && exit 9)
 | 
			
		||||
done
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								buildroot/bin/opt_find
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										33
									
								
								buildroot/bin/opt_find
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
#
 | 
			
		||||
# opt_find
 | 
			
		||||
# Find one or more Marlin options - Configuration lines starting with #define
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
MYNAME=$(basename $0)
 | 
			
		||||
 | 
			
		||||
[[ $# == 0 ]] && ONE="-h" || ONE=$1
 | 
			
		||||
 | 
			
		||||
COMM="(//\\s*)?" ; TYPE=""
 | 
			
		||||
case "$ONE" in
 | 
			
		||||
  -d|--disabled )
 | 
			
		||||
      shift ; COMM="(//\\s*)" ; TYPE="disabled " ;;
 | 
			
		||||
  -e|--enabled )
 | 
			
		||||
      shift ; COMM="" ; TYPE="enabled " ;;
 | 
			
		||||
  -h|--help )
 | 
			
		||||
      echo "$MYNAME [-d|--disabled|-e|--enabled] STRING ... Find matching Marlin configuration options."
 | 
			
		||||
      echo ; shift ;;
 | 
			
		||||
  -* )
 | 
			
		||||
      echo "Unknown option $ONE" ; shift ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
while [[ $# > 0 ]]; do
 | 
			
		||||
  DID=0
 | 
			
		||||
  for FN in Configuration Configuration_adv; do
 | 
			
		||||
    FOUND=$( grep -HEn "^\s*${COMM}#define\s+[A-Z0-9_]*${1}" "Marlin/$FN.h" 2>/dev/null )
 | 
			
		||||
    [[ -n "$FOUND" ]] && { echo "$FOUND" ; DID=1 ; }
 | 
			
		||||
  done
 | 
			
		||||
  ((DID)) || { echo "ERROR: ${MYNAME} - No ${TYPE}match for ${1}" ; exit 9; }
 | 
			
		||||
  shift
 | 
			
		||||
  echo
 | 
			
		||||
done
 | 
			
		||||
@@ -3,10 +3,15 @@
 | 
			
		||||
# exit on first failure
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
SED=$(which gsed || which sed)
 | 
			
		||||
SED=$(which gsed sed | head -n1)
 | 
			
		||||
 | 
			
		||||
# Logic for returning nonzero based on answer here: https://stackoverflow.com/a/15966279/104648
 | 
			
		||||
eval "${SED} -i '/\(\/\/\)*\([[:blank:]]*\)\(#define\s\+\b${1}\b\).*$/{s//\2\3 ${2}/;h};\${x;/./{x;q0};x;q9}' Marlin/Configuration.h" ||
 | 
			
		||||
eval "${SED} -i '/\(\/\/\)*\([[:blank:]]*\)\(#define\s\+\b${1}\b\).*$/{s//\2\3 ${2}/;h};\${x;/./{x;q0};x;q9}' Marlin/Configuration_adv.h" ||
 | 
			
		||||
eval "echo '#define ${@}' >>Marlin/Configuration_adv.h" ||
 | 
			
		||||
(echo "ERROR: opt_set Can't set or add ${1}" >&2 && exit 9)
 | 
			
		||||
while [[ $# > 1 ]]; do
 | 
			
		||||
  DID=0
 | 
			
		||||
  for FN in Configuration Configuration_adv; do
 | 
			
		||||
    "${SED}" -i "/^\(\s*\)\/*\s*\(#define\s\+${1}\b\) *\(.*\)$/{s//\1\2 ${2} \/\/ \3/;h};\${x;/./{x;q0};x;q9}" Marlin/$FN.h && DID=1
 | 
			
		||||
  done
 | 
			
		||||
  ((DID)) ||
 | 
			
		||||
    eval "echo '#define ${1} ${2}' >>Marlin/Configuration.h" ||
 | 
			
		||||
      (echo "ERROR: opt_set Can't set or add ${1}" >&2 && exit 9)
 | 
			
		||||
  shift 2
 | 
			
		||||
done
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,13 @@
 | 
			
		||||
IFS='/' read -r -a PINPATH <<< "$1"
 | 
			
		||||
DIR=${PINPATH[0]}
 | 
			
		||||
NAM=${PINPATH[1]}
 | 
			
		||||
PIN=$2
 | 
			
		||||
VAL=$3
 | 
			
		||||
 | 
			
		||||
SED=$(which gsed || which sed)
 | 
			
		||||
eval "${SED} -i '/\(\/\/\)*\(#define \+${PIN}\b\).*$/{s//\2 ${VAL}/;h};\${x;/./{x;q0};x;q9}' Marlin/src/pins/$DIR/pins_${NAM}.h" ||
 | 
			
		||||
(echo "ERROR: pins_set Can't find ${PIN}" >&2 && exit 9)
 | 
			
		||||
SED=$(which gsed sed | head -n1)
 | 
			
		||||
 | 
			
		||||
shift
 | 
			
		||||
while [[ $# > 1 ]]; do
 | 
			
		||||
  PIN=$1 ; VAL=$2
 | 
			
		||||
  eval "${SED} -i '/^[[:blank:]]*\(\/\/\)*[[:blank:]]*\(#define \+${PIN}\b\).*$/{s//\2 ${VAL}/;h};\${x;/./{x;q0};x;q9}' Marlin/src/pins/$DIR/pins_${NAM}.h" ||
 | 
			
		||||
  (echo "ERROR: pins_set Can't find ${PIN}" >&2 && exit 9)
 | 
			
		||||
  shift 2
 | 
			
		||||
done
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,11 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
git checkout Marlin/Configuration*.h 2>/dev/null
 | 
			
		||||
git checkout Marlin/src/pins/ramps/pins_RAMPS.h 2>/dev/null
 | 
			
		||||
rm -f Marlin/_Bootscreen.h Marlin/_Statusscreen.h
 | 
			
		||||
rm -f Marlin/_Bootscreen.h Marlin/_Statusscreen.h marlin_config.json .pio/build/mc.zip
 | 
			
		||||
 | 
			
		||||
if [[ $1 == '-d' || $1 == '--default' ]]; then
 | 
			
		||||
  use_example_configs
 | 
			
		||||
else
 | 
			
		||||
  git checkout Marlin/Configuration.h 2>/dev/null
 | 
			
		||||
  git checkout Marlin/Configuration_adv.h 2>/dev/null
 | 
			
		||||
  git checkout Marlin/src/pins/ramps/pins_RAMPS.h 2>/dev/null
 | 
			
		||||
fi
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										77
									
								
								buildroot/bin/run_tests
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										77
									
								
								buildroot/bin/run_tests
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
#
 | 
			
		||||
# run_tests
 | 
			
		||||
#
 | 
			
		||||
HERE="$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )"
 | 
			
		||||
TESTS="$HERE/../tests"
 | 
			
		||||
export PATH="$HERE:$TESTS:$PATH"
 | 
			
		||||
 | 
			
		||||
# exit on first failure
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
exec_test () {
 | 
			
		||||
  printf "\n\033[0;32m[Test $2] \033[0m$3...\n"
 | 
			
		||||
  # Check to see if we should skip tests
 | 
			
		||||
  if [[ -n "$4" ]] ; then
 | 
			
		||||
    if [[ ! "$3" =~ $4 ]] ; then
 | 
			
		||||
      printf "\033[1;33mSkipped\033[0m\n"
 | 
			
		||||
      return 0
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
  if [[ -z "$VERBOSE_PLATFORMIO" ]] ; then
 | 
			
		||||
    silent="--silent"
 | 
			
		||||
  else
 | 
			
		||||
    silent="-v"
 | 
			
		||||
  fi
 | 
			
		||||
  if platformio run --project-dir $1 -e $2 $silent; then
 | 
			
		||||
    printf "\033[0;32mPassed\033[0m\n"
 | 
			
		||||
    return 0
 | 
			
		||||
  else
 | 
			
		||||
    if [[ -n $GIT_RESET_HARD ]]; then
 | 
			
		||||
      git reset --hard HEAD
 | 
			
		||||
    else
 | 
			
		||||
      restore_configs
 | 
			
		||||
    fi
 | 
			
		||||
    printf "\033[0;31mFailed!\033[0m\n"
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
export -f exec_test
 | 
			
		||||
 | 
			
		||||
printf "Running \033[0;32m$2\033[0m Tests\n"
 | 
			
		||||
 | 
			
		||||
if [[ $2 = "ALL" ]]; then
 | 
			
		||||
  tests=("$TESTS"/*)
 | 
			
		||||
  for f in "${tests[@]}"; do
 | 
			
		||||
    testenv=$(basename $f)
 | 
			
		||||
    printf "Running \033[0;32m$f\033[0m Tests\n"
 | 
			
		||||
    exec_test $1 "$testenv --target clean" "Setup Build Environment"
 | 
			
		||||
    if [[ $GIT_RESET_HARD == "true" ]]; then
 | 
			
		||||
      git reset --hard HEAD
 | 
			
		||||
    else
 | 
			
		||||
      restore_configs
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
else
 | 
			
		||||
  exec_test $1 "$2 --target clean" "Setup Build Environment"
 | 
			
		||||
  test_name="$3"
 | 
			
		||||
  # If the test name is 1 or 2 digits, treat it as an index
 | 
			
		||||
  if [[ "$test_name" =~ ^[0-9][0-9]?$ ]] ; then
 | 
			
		||||
    # Find the test name that corresponds to that index
 | 
			
		||||
    test_name="$(cat $TESTS/$2 | grep -e '^exec_test' | sed -n "$3p" | sed "s/.*\$1 \$2 \"\([^\"]*\).*/\1/g")"
 | 
			
		||||
    if [[ -z "$test_name" ]] ; then
 | 
			
		||||
      # Fail if none matches
 | 
			
		||||
      printf "\033[0;31mCould not find test \033[0m#$3\033[0;31m in \033[0mbuildroot/tests/$2\n"
 | 
			
		||||
      exit 1
 | 
			
		||||
    else
 | 
			
		||||
      printf "\033[0;32mMatching test \033[0m#$3\033[0;32m: '\033[0m$test_name\033[0;32m'\n"
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
  $TESTS/$2 $1 $2 "$test_name"
 | 
			
		||||
  if [[ $GIT_RESET_HARD == "true" ]]; then
 | 
			
		||||
    git reset --hard HEAD
 | 
			
		||||
  else
 | 
			
		||||
    restore_configs
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
printf "\033[0;32mAll tests completed successfully\033[0m\n"
 | 
			
		||||
@@ -6,11 +6,12 @@
 | 
			
		||||
TMPDIR=`mktemp -d`
 | 
			
		||||
 | 
			
		||||
# Reformat a single file to tmp/
 | 
			
		||||
uncrustify -l CPP -c ./buildroot/share/extras/uncrustify.cfg -f "$1" >$TMPDIR/uncrustify.out
 | 
			
		||||
 | 
			
		||||
# Replace the original file
 | 
			
		||||
cp "$TMPDIR/uncrustify.out" "$1"
 | 
			
		||||
if uncrustify -l CPP -c ./buildroot/share/extras/uncrustify.cfg -f "$1" >$TMPDIR/uncrustify.out ; then
 | 
			
		||||
  cp "$TMPDIR/uncrustify.out" "$1"  ; # Replace the original file
 | 
			
		||||
else
 | 
			
		||||
  echo "Something went wrong with uncrustify."
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Clean up, deliberately
 | 
			
		||||
rm "$TMPDIR/uncrustify.out"
 | 
			
		||||
[[ -f "$TMPDIR/uncrustify.out" ]] && rm "$TMPDIR/uncrustify.out"
 | 
			
		||||
rmdir "$TMPDIR"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,44 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
IFS=: read -r PART1 PART2 <<< "$@"
 | 
			
		||||
[ -n "${PART2}" ] && { REPO="$PART1" ; RDIR="${PART2// /%20}" ; } \
 | 
			
		||||
                  || { REPO=bugfix-2.0.x   ; RDIR="${PART1// /%20}" ; }
 | 
			
		||||
EXAMPLES="https://raw.githubusercontent.com/MarlinFirmware/Configurations/$REPO/config/examples"
 | 
			
		||||
#
 | 
			
		||||
# use_example_configs [repo:]configpath
 | 
			
		||||
#
 | 
			
		||||
# Examples:
 | 
			
		||||
#   use_example_configs
 | 
			
		||||
#   use_example_configs Creality/CR-10/CrealityV1
 | 
			
		||||
#   use_example_configs release-2.0.9.4:Creality/CR-10/CrealityV1
 | 
			
		||||
#
 | 
			
		||||
# If a configpath has spaces (or quotes) escape them or enquote the path
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
which curl >/dev/null && TOOL='curl -L -s -S -f -o wgot'
 | 
			
		||||
which wget >/dev/null && TOOL='wget -q -O wgot'
 | 
			
		||||
 | 
			
		||||
CURR=$(git branch 2>/dev/null | grep ^* | sed 's/\* //g')
 | 
			
		||||
[[ $CURR == "bugfix-2.0.x" ]] && BRANCH=bugfix-2.0.x || BRANCH=bugfix-2.1.x
 | 
			
		||||
 | 
			
		||||
REPO=$BRANCH
 | 
			
		||||
 | 
			
		||||
if [[ $# > 0 ]]; then
 | 
			
		||||
  IFS=: read -r PART1 PART2 <<< "$@"
 | 
			
		||||
  [[ -n $PART2 ]] && { UDIR="$PART2" ; REPO="$PART1" ; } \
 | 
			
		||||
                  || { UDIR="$PART1" ; }
 | 
			
		||||
  RDIR="${UDIR// /%20}"
 | 
			
		||||
  echo "Fetching $UDIR configurations from $REPO..."
 | 
			
		||||
  EXAMPLES="examples/$RDIR"
 | 
			
		||||
else
 | 
			
		||||
  EXAMPLES="default"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
CONFIGS="https://raw.githubusercontent.com/MarlinFirmware/Configurations/$REPO/config/${EXAMPLES}"
 | 
			
		||||
 | 
			
		||||
restore_configs
 | 
			
		||||
 | 
			
		||||
cd Marlin
 | 
			
		||||
 | 
			
		||||
$TOOL "$EXAMPLES/$RDIR/Configuration.h"     >/dev/null 2>&1 && mv wgot Configuration.h
 | 
			
		||||
$TOOL "$EXAMPLES/$RDIR/Configuration_adv.h" >/dev/null 2>&1 && mv wgot Configuration_adv.h
 | 
			
		||||
$TOOL "$EXAMPLES/$RDIR/_Bootscreen.h"       >/dev/null 2>&1 && mv wgot _Bootscreen.h
 | 
			
		||||
$TOOL "$EXAMPLES/$RDIR/_Statusscreen.h"     >/dev/null 2>&1 && mv wgot _Statusscreen.h
 | 
			
		||||
$TOOL "$CONFIGS/Configuration.h"     >/dev/null 2>&1 && mv wgot Configuration.h
 | 
			
		||||
$TOOL "$CONFIGS/Configuration_adv.h" >/dev/null 2>&1 && mv wgot Configuration_adv.h
 | 
			
		||||
$TOOL "$CONFIGS/_Bootscreen.h"       >/dev/null 2>&1 && mv wgot _Bootscreen.h
 | 
			
		||||
$TOOL "$CONFIGS/_Statusscreen.h"     >/dev/null 2>&1 && mv wgot _Statusscreen.h
 | 
			
		||||
 | 
			
		||||
rm -f wgot
 | 
			
		||||
cd - >/dev/null
 | 
			
		||||
 
 | 
			
		||||
@@ -5,21 +5,16 @@
 | 
			
		||||
    "extra_flags": "-DSTM32F401xx",
 | 
			
		||||
    "f_cpu": "84000000L",
 | 
			
		||||
    "hwids": [
 | 
			
		||||
      [
 | 
			
		||||
        "0x1EAF",
 | 
			
		||||
        "0x0003"
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        "0x0483",
 | 
			
		||||
        "0x3748"
 | 
			
		||||
        "0xDF11"
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "ldscript": "stm32f401xe.ld",
 | 
			
		||||
    "mcu": "stm32f401vet6",
 | 
			
		||||
    "variant": "STEVAL_F401VE"
 | 
			
		||||
    "mcu": "stm32f401rct6",
 | 
			
		||||
    "variant": "MARLIN_ARTILLERY_RUBY"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F401VE",
 | 
			
		||||
    "jlink_device": "STM32F401RC",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F40x.svd",
 | 
			
		||||
    "tools": {
 | 
			
		||||
@@ -45,11 +40,11 @@
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "stm32cube"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F401VE (96k RAM. 512k Flash)",
 | 
			
		||||
  "name": "STM32F401RC (64k RAM. 256k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 98304,
 | 
			
		||||
    "maximum_size": 514288,
 | 
			
		||||
    "maximum_ram_size": 65536,
 | 
			
		||||
    "maximum_size": 262144,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
							
								
								
									
										47
									
								
								buildroot/share/PlatformIO/boards/marlin_BTT_EBB42_V1_1.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								buildroot/share/PlatformIO/boards/marlin_BTT_EBB42_V1_1.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m0plus",
 | 
			
		||||
    "extra_flags": "-DSTM32G0xx -DSTM32G0B1xx",
 | 
			
		||||
    "f_cpu": "64000000L",
 | 
			
		||||
    "framework_extra_flags": {
 | 
			
		||||
      "arduino": "-D__CORTEX_SC=0"
 | 
			
		||||
    },
 | 
			
		||||
    "mcu": "stm32g0b1cbt6",
 | 
			
		||||
    "product_line": "STM32G0B1xx",
 | 
			
		||||
    "variant": "MARLIN_BTT_EBB42_V1_1"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "default_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "jlink_device": "STM32G0B1CB",
 | 
			
		||||
    "onboard_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "openocd_target": "stm32g0x",
 | 
			
		||||
    "svd_path": "STM32G0B1.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "cmsis",
 | 
			
		||||
    "libopencm3",
 | 
			
		||||
    "stm32cube",
 | 
			
		||||
    "zephyr"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32G0B1CB",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "maximum_ram_size": 147456,
 | 
			
		||||
    "maximum_size": 131072,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "jlink",
 | 
			
		||||
      "cmsis-dap",
 | 
			
		||||
      "blackmagic",
 | 
			
		||||
      "mbed"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-mainstream-mcus/stm32g0-series/stm32g0x1.html",
 | 
			
		||||
  "vendor": "ST"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								buildroot/share/PlatformIO/boards/marlin_BTT_SKR_SE_BX.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								buildroot/share/PlatformIO/boards/marlin_BTT_SKR_SE_BX.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m7",
 | 
			
		||||
    "extra_flags": "-DSTM32H743xx",
 | 
			
		||||
    "f_cpu": "400000000L",
 | 
			
		||||
    "mcu": "stm32h743iit6",
 | 
			
		||||
    "variant": "MARLIN_BTT_SKR_SE_BX"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32H743II",
 | 
			
		||||
    "openocd_target": "stm32h7x",
 | 
			
		||||
    "svd_path": "STM32H7x3.svd",
 | 
			
		||||
    "tools": {
 | 
			
		||||
      "stlink": {
 | 
			
		||||
        "server": {
 | 
			
		||||
          "arguments": [
 | 
			
		||||
            "-f",
 | 
			
		||||
            "scripts/interface/stlink.cfg",
 | 
			
		||||
            "-c",
 | 
			
		||||
            "transport select hla_swd",
 | 
			
		||||
            "-f",
 | 
			
		||||
            "scripts/target/stm32h7x.cfg",
 | 
			
		||||
            "-c",
 | 
			
		||||
            "reset_config none"
 | 
			
		||||
          ],
 | 
			
		||||
          "executable": "bin/openocd",
 | 
			
		||||
          "package": "tool-openocd"
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "stm32cube"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32H743II (1024k RAM. 2048k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 1048576,
 | 
			
		||||
    "maximum_size": 2097152,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink",
 | 
			
		||||
      "cmsis-dap"
 | 
			
		||||
    ],
 | 
			
		||||
    "offset_address": "0x8020000",
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32h743ii.html",
 | 
			
		||||
  "vendor": "Generic"
 | 
			
		||||
}
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407vgt6",
 | 
			
		||||
    "variant": "BIGTREE_BTT002"
 | 
			
		||||
    "variant": "MARLIN_BIGTREE_BTT002"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F407VG",
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F4 -DSTM32F407xx -DSTM32F40_41xxx",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "hwids": [
 | 
			
		||||
      [
 | 
			
		||||
        "0x1EAF",
 | 
			
		||||
        "0x0003"
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        "0x0483",
 | 
			
		||||
        "0x3748"
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407vet6",
 | 
			
		||||
    "variant": "MARLIN_BIGTREE_BTT002"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F407VE",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F40x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F407VE (192k RAM. 512k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 524288,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "offset_address": "0x8008000",
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f407ve.html",
 | 
			
		||||
  "vendor": "ST"
 | 
			
		||||
}
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407zgt6",
 | 
			
		||||
    "variant": "BIGTREE_GTR_V1"
 | 
			
		||||
    "variant": "MARLIN_BIGTREE_GTR_V1"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F407ZG",
 | 
			
		||||
@@ -0,0 +1,50 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F4 -DSTM32F429xx",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "mcu": "stm32f429zgt6",
 | 
			
		||||
    "product_line": "STM32F429xx",
 | 
			
		||||
    "variant": "MARLIN_BIGTREE_OCTOPUS_PRO_V1_F429"
 | 
			
		||||
  },
 | 
			
		||||
  "connectivity": [
 | 
			
		||||
    "can"
 | 
			
		||||
  ],
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "default_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "jlink_device": "STM32F429ZG",
 | 
			
		||||
    "onboard_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "openocd_board": "stm32f429",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F429x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "cmsis",
 | 
			
		||||
    "mbed",
 | 
			
		||||
    "stm32cube",
 | 
			
		||||
    "libopencm3",
 | 
			
		||||
    "zephyr"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F429ZG (128k RAM, 64k CCM RAM, 1024k Flash",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 1048576,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f429-439.html",
 | 
			
		||||
  "vendor": "ST"
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,35 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F446xx",
 | 
			
		||||
    "f_cpu": "180000000L",
 | 
			
		||||
    "mcu": "stm32f446zet6",
 | 
			
		||||
    "variant": "MARLIN_BIGTREE_OCTOPUS_V1"
 | 
			
		||||
  },
 | 
			
		||||
  "connectivity": [
 | 
			
		||||
    "can"
 | 
			
		||||
  ],
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F446ZE",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F446x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "stm32cube"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F446ZE (128k RAM. 512k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 524288,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "jlink",
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "blackmagic",
 | 
			
		||||
      "serial"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f446.html",
 | 
			
		||||
  "vendor": "Generic"
 | 
			
		||||
}
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407zgt6",
 | 
			
		||||
    "variant": "BIGTREE_SKR_PRO_1v1"
 | 
			
		||||
    "variant": "MARLIN_BIGTREE_SKR_PRO_11"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F407ZG",
 | 
			
		||||
@@ -2,8 +2,8 @@
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F407xx",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "extra_flags": "-DSTM32F401xx",
 | 
			
		||||
    "f_cpu": "84000000L",
 | 
			
		||||
    "hwids": [
 | 
			
		||||
      [
 | 
			
		||||
        "0x1EAF",
 | 
			
		||||
@@ -14,12 +14,12 @@
 | 
			
		||||
        "0x3748"
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407zgt6",
 | 
			
		||||
    "variant": "LERDGE",
 | 
			
		||||
    "ldscript": "LERDGE.ld"
 | 
			
		||||
    "ldscript": "ldscript.ld",
 | 
			
		||||
    "mcu": "stm32f401rct6",
 | 
			
		||||
    "variant": "MARLIN_CREALITY_STM32F401RC"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F407ZG",
 | 
			
		||||
    "jlink_device": "STM32F401RC",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F40x.svd",
 | 
			
		||||
    "tools": {
 | 
			
		||||
@@ -45,11 +45,11 @@
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "stm32cube"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F407ZGT6(192k RAM. 1024k Flash)",
 | 
			
		||||
  "name": "STM32F401RC (64k RAM. 256k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 196608,
 | 
			
		||||
    "maximum_size": 1048576,
 | 
			
		||||
    "maximum_ram_size": 65536,
 | 
			
		||||
    "maximum_size": 262144,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
@@ -60,6 +60,6 @@
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f407ZG.html",
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f401rc.html",
 | 
			
		||||
  "vendor": "Generic"
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,65 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F401xx",
 | 
			
		||||
    "f_cpu": "84000000L",
 | 
			
		||||
    "hwids": [
 | 
			
		||||
      [
 | 
			
		||||
        "0x1EAF",
 | 
			
		||||
        "0x0003"
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        "0x0483",
 | 
			
		||||
        "0x3748"
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f401rct6",
 | 
			
		||||
    "variant": "MARLIN_FYSETC_CHEETAH_V20"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F401RC",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F40x.svd",
 | 
			
		||||
    "tools": {
 | 
			
		||||
      "stlink": {
 | 
			
		||||
        "server": {
 | 
			
		||||
          "arguments": [
 | 
			
		||||
            "-f",
 | 
			
		||||
            "scripts/interface/stlink.cfg",
 | 
			
		||||
            "-c",
 | 
			
		||||
            "transport select hla_swd",
 | 
			
		||||
            "-f",
 | 
			
		||||
            "scripts/target/stm32f4x.cfg",
 | 
			
		||||
            "-c",
 | 
			
		||||
            "reset_config none"
 | 
			
		||||
          ],
 | 
			
		||||
          "executable": "bin/openocd",
 | 
			
		||||
          "package": "tool-openocd"
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "stm32cube"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F401RC (64k RAM. 256k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 65536,
 | 
			
		||||
    "maximum_size": 262144,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink"
 | 
			
		||||
    ],
 | 
			
		||||
	"offset_address": "0x8008000",
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.fysetc.com",
 | 
			
		||||
  "vendor": "Generic"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								buildroot/share/PlatformIO/boards/marlin_MKS_SKIPR_V1.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								buildroot/share/PlatformIO/boards/marlin_MKS_SKIPR_V1.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F4 -DSTM32F407xx",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "offset": "0xC000",
 | 
			
		||||
    "hwids": [
 | 
			
		||||
      [
 | 
			
		||||
        "0x1EAF",
 | 
			
		||||
        "0x0003"
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        "0x0483",
 | 
			
		||||
        "0x3748"
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407vet6",
 | 
			
		||||
    "product_line": "STM32F407xx",
 | 
			
		||||
    "variant": "MARLIN_MKS_SKIPR_V1"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "default_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "jlink_device": "STM32F407VE",
 | 
			
		||||
    "openocd_extra_args": [
 | 
			
		||||
      "-c",
 | 
			
		||||
      "reset_config none"
 | 
			
		||||
    ],
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F40x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F407VE (128k RAM, 64k CCM RAM, 512k Flash",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 524288,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "offset_address": "0x0800C000",
 | 
			
		||||
    "require_upload_port": false,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f407ve.html",
 | 
			
		||||
  "vendor": "ST"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								buildroot/share/PlatformIO/boards/marlin_STM32F401RC.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								buildroot/share/PlatformIO/boards/marlin_STM32F401RC.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F401xC -DSTM32F4xx",
 | 
			
		||||
    "f_cpu": "84000000L",
 | 
			
		||||
    "mcu": "stm32f401rct6",
 | 
			
		||||
    "product_line": "STM32F401xC",
 | 
			
		||||
    "variant": "MARLIN_F401RC"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F401RC",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F401x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "cmsis",
 | 
			
		||||
    "spl",
 | 
			
		||||
    "stm32cube",
 | 
			
		||||
    "libopencm3"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F401RC (64k RAM. 256k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "maximum_ram_size": 65536,
 | 
			
		||||
    "maximum_size": 262144,
 | 
			
		||||
    "protocol": "serial",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "blackmagic",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink",
 | 
			
		||||
      "serial",
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f401rc.html",
 | 
			
		||||
  "vendor": "Generic"
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,56 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F407xx -DSTM32F4",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "hwids": [
 | 
			
		||||
      [
 | 
			
		||||
        "0x1EAF",
 | 
			
		||||
        "0x0003"
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        "0x0483",
 | 
			
		||||
        "0x3748"
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407vet6",
 | 
			
		||||
    "product_line": "STM32F407xx",
 | 
			
		||||
    "variant": "Generic_F4x7Vx"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "default_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "jlink_device": "STM32F407VE",
 | 
			
		||||
    "openocd_extra_args": [
 | 
			
		||||
      "-c",
 | 
			
		||||
      "reset_config none"
 | 
			
		||||
    ],
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F40x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "cmsis",
 | 
			
		||||
    "stm32cube",
 | 
			
		||||
    "libopencm3"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F407VE (128k RAM, 64k CCM RAM, 512k Flash",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 524288,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f4-series/stm32f407-417/stm32f407vg.html",
 | 
			
		||||
  "vendor": "Generic"
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,56 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F407xx -DSTM32F4",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "hwids": [
 | 
			
		||||
      [
 | 
			
		||||
        "0x1EAF",
 | 
			
		||||
        "0x0003"
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        "0x0483",
 | 
			
		||||
        "0x3748"
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407vgt6",
 | 
			
		||||
    "product_line": "STM32F407xx",
 | 
			
		||||
    "variant": "Generic_F4x7Vx"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "default_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "jlink_device": "STM32F407VG",
 | 
			
		||||
    "openocd_extra_args": [
 | 
			
		||||
      "-c",
 | 
			
		||||
      "reset_config none"
 | 
			
		||||
    ],
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F40x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "cmsis",
 | 
			
		||||
    "stm32cube",
 | 
			
		||||
    "libopencm3"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F407VG (128k RAM, 64k CCM RAM, 1024k Flash",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 1048576,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f4-series/stm32f407-417/stm32f407vg.html",
 | 
			
		||||
  "vendor": "Generic"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								buildroot/share/PlatformIO/boards/marlin_STM32F407ZE.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								buildroot/share/PlatformIO/boards/marlin_STM32F407ZE.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F4 -DSTM32F407xx",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "mcu": "stm32f407zgt6",
 | 
			
		||||
    "product_line": "STM32F407xx",
 | 
			
		||||
    "variant": "MARLIN_F407ZE"
 | 
			
		||||
  },
 | 
			
		||||
  "connectivity": [
 | 
			
		||||
    "can"
 | 
			
		||||
  ],
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "default_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "jlink_device": "STM32F407ZE",
 | 
			
		||||
    "onboard_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "openocd_board": "stm32f407",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F407x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "cmsis",
 | 
			
		||||
    "mbed",
 | 
			
		||||
    "stm32cube",
 | 
			
		||||
    "libopencm3",
 | 
			
		||||
    "zephyr"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F407ZE (128k RAM, 64k CCM RAM, 512k Flash",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 524288,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f407-417.html",
 | 
			
		||||
  "vendor": "ST"
 | 
			
		||||
}
 | 
			
		||||
@@ -14,8 +14,7 @@
 | 
			
		||||
        "0x3748"
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407zgt6",
 | 
			
		||||
    "variant": "FLY_F407ZG"
 | 
			
		||||
    "mcu": "stm32f407zgt6"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F407ZG",
 | 
			
		||||
@@ -49,7 +48,7 @@
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 196608,
 | 
			
		||||
    "maximum_size": 1048576,
 | 
			
		||||
    "protocol": "dfu",
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
							
								
								
									
										50
									
								
								buildroot/share/PlatformIO/boards/marlin_STM32F429VGT6.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								buildroot/share/PlatformIO/boards/marlin_STM32F429VGT6.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F4 -DSTM32F429xx",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "mcu": "stm32f429vgt6",
 | 
			
		||||
    "product_line": "STM32F429xx",
 | 
			
		||||
    "variant": "MARLIN_F4x7Vx"
 | 
			
		||||
  },
 | 
			
		||||
  "connectivity": [
 | 
			
		||||
    "can"
 | 
			
		||||
  ],
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "default_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "jlink_device": "STM32F429VG",
 | 
			
		||||
    "onboard_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "openocd_board": "stm32f429",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F429x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "cmsis",
 | 
			
		||||
    "mbed",
 | 
			
		||||
    "stm32cube",
 | 
			
		||||
    "libopencm3",
 | 
			
		||||
    "zephyr"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F429VG (128k RAM, 64k CCM RAM, 1024k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 1048576,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f429-439.html",
 | 
			
		||||
  "vendor": "ST"
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,35 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F446xx",
 | 
			
		||||
    "f_cpu": "180000000L",
 | 
			
		||||
    "mcu": "stm32f446zet6",
 | 
			
		||||
    "variant": "MARLIN_F446Zx_TRONXY"
 | 
			
		||||
  },
 | 
			
		||||
  "connectivity": [
 | 
			
		||||
    "can"
 | 
			
		||||
  ],
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F446ZE",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F446x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "stm32cube"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F446ZE (128k RAM. 512k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 524288,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "jlink",
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "blackmagic",
 | 
			
		||||
      "serial"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f446.html",
 | 
			
		||||
  "vendor": "Generic"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								buildroot/share/PlatformIO/boards/marlin_STM32G0B1RE.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								buildroot/share/PlatformIO/boards/marlin_STM32G0B1RE.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m0plus",
 | 
			
		||||
    "extra_flags": "-DSTM32G0xx -DSTM32G0B1xx",
 | 
			
		||||
    "f_cpu": "64000000L",
 | 
			
		||||
    "framework_extra_flags": {
 | 
			
		||||
      "arduino": "-D__CORTEX_SC=0"
 | 
			
		||||
    },
 | 
			
		||||
    "mcu": "stm32g0b1ret6",
 | 
			
		||||
    "product_line": "STM32G0B1xx",
 | 
			
		||||
    "variant": "MARLIN_G0B1RE"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "default_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "jlink_device": "STM32G0B1RE",
 | 
			
		||||
    "onboard_tools": [
 | 
			
		||||
      "stlink"
 | 
			
		||||
    ],
 | 
			
		||||
    "openocd_target": "stm32g0x",
 | 
			
		||||
    "svd_path": "STM32G0B1.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "cmsis",
 | 
			
		||||
    "libopencm3",
 | 
			
		||||
    "stm32cube",
 | 
			
		||||
    "zephyr"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32G0B1RE",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "maximum_ram_size": 147456,
 | 
			
		||||
    "maximum_size": 524288,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "jlink",
 | 
			
		||||
      "cmsis-dap",
 | 
			
		||||
      "blackmagic",
 | 
			
		||||
      "mbed"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-mainstream-mcus/stm32g0-series/stm32g0x1.html",
 | 
			
		||||
  "vendor": "ST"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								buildroot/share/PlatformIO/boards/marlin_STM32H743Vx.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								buildroot/share/PlatformIO/boards/marlin_STM32H743Vx.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m7",
 | 
			
		||||
    "extra_flags": "-DSTM32H7xx -DSTM32H743xx",
 | 
			
		||||
    "f_cpu": "480000000L",
 | 
			
		||||
    "mcu": "stm32h743vit6",
 | 
			
		||||
    "product_line": "STM32H743xx",
 | 
			
		||||
    "variant": "MARLIN_H743Vx"
 | 
			
		||||
  },
 | 
			
		||||
  "connectivity": [
 | 
			
		||||
    "can",
 | 
			
		||||
    "ethernet"
 | 
			
		||||
  ],
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32H743VI",
 | 
			
		||||
    "openocd_target": "stm32h7x",
 | 
			
		||||
    "svd_path": "STM32H7x3.svd",
 | 
			
		||||
    "tools": {
 | 
			
		||||
      "stlink": {
 | 
			
		||||
        "server": {
 | 
			
		||||
          "arguments": [
 | 
			
		||||
            "-f",
 | 
			
		||||
            "scripts/interface/stlink.cfg",
 | 
			
		||||
            "-c",
 | 
			
		||||
            "transport select hla_swd",
 | 
			
		||||
            "-f",
 | 
			
		||||
            "scripts/target/stm32h7x.cfg",
 | 
			
		||||
            "-c",
 | 
			
		||||
            "reset_config none"
 | 
			
		||||
          ],
 | 
			
		||||
          "executable": "bin/openocd",
 | 
			
		||||
          "package": "tool-openocd"
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "stm32cube"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32H743VI (1024k RAM. 2048k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 1048576,
 | 
			
		||||
    "maximum_size": 2097152,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink",
 | 
			
		||||
      "cmsis-dap"
 | 
			
		||||
    ],
 | 
			
		||||
    "offset_address": "0x8020000",
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32h743vi.html",
 | 
			
		||||
  "vendor": "ST"
 | 
			
		||||
}
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
    "ldscript": "linker_scripts/gcc/flash.ld",
 | 
			
		||||
    "mcu": "at91sam3x8e",
 | 
			
		||||
    "usb_product": "Archim",
 | 
			
		||||
    "variant": "archim"
 | 
			
		||||
    "variant": "MARLIN_ARCHIM"
 | 
			
		||||
  },
 | 
			
		||||
  "connectivity": [
 | 
			
		||||
    "can"
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F407xx",
 | 
			
		||||
    "extra_flags": "-DSTM32F407xx -DARDUINO_BLACK_F407VE",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "hwids": [
 | 
			
		||||
      [
 | 
			
		||||
@@ -48,7 +48,7 @@
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 514288,
 | 
			
		||||
    "maximum_size": 524288,
 | 
			
		||||
    "protocol": "stlink",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
@@ -15,8 +15,7 @@
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f103zet6",
 | 
			
		||||
    "variant": "CHITU_F103",
 | 
			
		||||
    "ldscript": "chitu_f103.ld"
 | 
			
		||||
    "variant": "marlin_maple_CHITU_F103"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F103ZE",
 | 
			
		||||
@@ -18,7 +18,7 @@
 | 
			
		||||
      "ldscript": "stm32f103xc.ld"
 | 
			
		||||
    },
 | 
			
		||||
    "mcu": "stm32f103rct6",
 | 
			
		||||
    "variant": "MEEB_3DP"
 | 
			
		||||
    "variant": "marlin_maple_MEEB_3DP"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F103RC",
 | 
			
		||||
@@ -0,0 +1,51 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F407xx",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "hwids": [
 | 
			
		||||
      [
 | 
			
		||||
        "0x0483",
 | 
			
		||||
        "0xdf11"
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        "0x1EAF",
 | 
			
		||||
        "0x0003"
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        "0x0483",
 | 
			
		||||
        "0x3748"
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407vet6",
 | 
			
		||||
    "variant": "MARLIN_F407VE"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F407VE",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F40x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "stm32cube"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F407VE (192k RAM. 512k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 524288,
 | 
			
		||||
    "protocol": "dfu",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink",
 | 
			
		||||
      "blackmagic"
 | 
			
		||||
    ],
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f407ve.html",
 | 
			
		||||
  "vendor": "Generic"
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,51 @@
 | 
			
		||||
{
 | 
			
		||||
  "build": {
 | 
			
		||||
    "core": "stm32",
 | 
			
		||||
    "cpu": "cortex-m4",
 | 
			
		||||
    "extra_flags": "-DSTM32F407xx",
 | 
			
		||||
    "f_cpu": "168000000L",
 | 
			
		||||
    "hwids": [
 | 
			
		||||
      [
 | 
			
		||||
        "0x0483",
 | 
			
		||||
        "0xdf11"
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        "0x1EAF",
 | 
			
		||||
        "0x0003"
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        "0x0483",
 | 
			
		||||
        "0x3748"
 | 
			
		||||
      ]
 | 
			
		||||
    ],
 | 
			
		||||
    "mcu": "stm32f407vet6",
 | 
			
		||||
    "variant": "MARLIN_F407VE"
 | 
			
		||||
  },
 | 
			
		||||
  "debug": {
 | 
			
		||||
    "jlink_device": "STM32F407VE",
 | 
			
		||||
    "openocd_target": "stm32f4x",
 | 
			
		||||
    "svd_path": "STM32F40x.svd"
 | 
			
		||||
  },
 | 
			
		||||
  "frameworks": [
 | 
			
		||||
    "arduino",
 | 
			
		||||
    "stm32cube"
 | 
			
		||||
  ],
 | 
			
		||||
  "name": "STM32F407VE (192k RAM. 512k Flash)",
 | 
			
		||||
  "upload": {
 | 
			
		||||
    "disable_flushing": false,
 | 
			
		||||
    "maximum_ram_size": 131072,
 | 
			
		||||
    "maximum_size": 524288,
 | 
			
		||||
    "protocol": "dfu",
 | 
			
		||||
    "protocols": [
 | 
			
		||||
      "stlink",
 | 
			
		||||
      "dfu",
 | 
			
		||||
      "jlink",
 | 
			
		||||
      "blackmagic"
 | 
			
		||||
    ],
 | 
			
		||||
    "require_upload_port": true,
 | 
			
		||||
    "use_1200bps_touch": false,
 | 
			
		||||
    "wait_for_upload_port": false
 | 
			
		||||
  },
 | 
			
		||||
  "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32f407ve.html",
 | 
			
		||||
  "vendor": "Generic"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								buildroot/share/PlatformIO/debugging/launch.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								buildroot/share/PlatformIO/debugging/launch.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Remote debugging on STM32 using the "Cortex Debug" extension.
 | 
			
		||||
 *
 | 
			
		||||
 * Copy one or more of the configurations items below into .vscode/launch.json
 | 
			
		||||
 * to add those debug options to the PlatformIO IDE "Run & Debug" panel.
 | 
			
		||||
 *
 | 
			
		||||
 * Examples for BigTreeTech SKR 2 (USB) and Native Simulator. Modify for your own build.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: The PlatformIO extension will remove items when regenerating launch.json.
 | 
			
		||||
 */
 | 
			
		||||
{
 | 
			
		||||
    "version": "0.2.0",
 | 
			
		||||
    "configurations": [
 | 
			
		||||
        {
 | 
			
		||||
            "name": "Debug STM32 (ST-Link)",
 | 
			
		||||
            "request": "launch",
 | 
			
		||||
            "type": "cortex-debug",
 | 
			
		||||
            "servertype": "openocd",
 | 
			
		||||
            "cwd": "${workspaceRoot}",
 | 
			
		||||
            "showDevDebugOutput": false,
 | 
			
		||||
            "configFiles": [ "interface/stlink.cfg", "target/stm32f4x.cfg" ],
 | 
			
		||||
            "device": "stlink",
 | 
			
		||||
            "executable": "${workspaceRoot}/.pio/build/BIGTREE_SKR_2_USB_debug/firmware.elf",
 | 
			
		||||
            "openOCDLaunchCommands": [ "init", "reset init" ],
 | 
			
		||||
            "svdFile": "${env:HOME}/.platformio/platforms/ststm32@12.1.1/misc/svd/STM32F40x.svd",
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "Launch Sim (ggdb)",
 | 
			
		||||
            "request": "launch",
 | 
			
		||||
            "type": "cppdbg",
 | 
			
		||||
            "cwd": "${workspaceRoot}",
 | 
			
		||||
            "program": "${workspaceRoot}/.pio/build/simulator_macos_debug/debug/MarlinSimulator",
 | 
			
		||||
            //"program": "${workspaceRoot}/.pio/build/simulator_linux_debug/MarlinSimulator",
 | 
			
		||||
            //"program": "${workspaceRoot}/.pio/build/simulator_windows/MarlinSimulator",
 | 
			
		||||
            "miDebuggerPath": "/opt/local/bin/ggdb",
 | 
			
		||||
            "MIMode": "gdb"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "Launch Sim (lldb)",
 | 
			
		||||
            "request": "launch",
 | 
			
		||||
            "type": "cppdbg",
 | 
			
		||||
            "cwd": "${workspaceRoot}",
 | 
			
		||||
            "program": "${workspaceRoot}/.pio/build/simulator_macos_debug/debug/MarlinSimulator",
 | 
			
		||||
            //"program": "${workspaceRoot}/.pio/build/simulator_linux_debug/MarlinSimulator",
 | 
			
		||||
            //"program": "${workspaceRoot}/.pio/build/simulator_windows/MarlinSimulator",
 | 
			
		||||
            //"targetArchitecture": "arm64",
 | 
			
		||||
            "MIMode": "lldb"
 | 
			
		||||
        }
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
MEMORY
 | 
			
		||||
{
 | 
			
		||||
  ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K - 40
 | 
			
		||||
  rom (rx)  : ORIGIN = 0x08007000, LENGTH = 512K - 28K - 4K
 | 
			
		||||
  rom (rx)  : ORIGIN = 0x08005000, LENGTH = 256K - 20K - 4K
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Provide memory region aliases for common.inc */
 | 
			
		||||
@@ -1,11 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Linker script for Generic STM32F103RC boards, using the generic bootloader (which takes the lower 8k of memory)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
MEMORY
 | 
			
		||||
{
 | 
			
		||||
	ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K
 | 
			
		||||
	rom (rx)  : ORIGIN = 0x08008000, LENGTH = 256K - 32K
 | 
			
		||||
  ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K - 40
 | 
			
		||||
  rom (rx)  : ORIGIN = 0x08005000, LENGTH = 512K - 20K - 4K
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Provide memory region aliases for common.inc */
 | 
			
		||||
							
								
								
									
										14
									
								
								buildroot/share/PlatformIO/ldscripts/crealityPro.ld
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								buildroot/share/PlatformIO/ldscripts/crealityPro.ld
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
MEMORY
 | 
			
		||||
{
 | 
			
		||||
  ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K - 40
 | 
			
		||||
  rom (rx)  : ORIGIN = 0x08010000, LENGTH = 512K - 64K
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Provide memory region aliases for common.inc */
 | 
			
		||||
REGION_ALIAS("REGION_TEXT", rom);
 | 
			
		||||
REGION_ALIAS("REGION_DATA", ram);
 | 
			
		||||
REGION_ALIAS("REGION_BSS", ram);
 | 
			
		||||
REGION_ALIAS("REGION_RODATA", rom);
 | 
			
		||||
 | 
			
		||||
/* Let common.inc handle the real work. */
 | 
			
		||||
INCLUDE common.inc
 | 
			
		||||
							
								
								
									
										14
									
								
								buildroot/share/PlatformIO/ldscripts/eryone_ery32_mini.ld
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								buildroot/share/PlatformIO/ldscripts/eryone_ery32_mini.ld
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
MEMORY
 | 
			
		||||
{
 | 
			
		||||
  ram (rwx) : ORIGIN = 0x20000000, LENGTH =  64K -  4K
 | 
			
		||||
  rom (rx)  : ORIGIN = 0x08004000, LENGTH = 512K - 16K
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Provide memory region aliases for common.inc */
 | 
			
		||||
REGION_ALIAS("REGION_TEXT", rom);
 | 
			
		||||
REGION_ALIAS("REGION_DATA", ram);
 | 
			
		||||
REGION_ALIAS("REGION_BSS", ram);
 | 
			
		||||
REGION_ALIAS("REGION_RODATA", rom);
 | 
			
		||||
 | 
			
		||||
/* Let common.inc handle the real work. */
 | 
			
		||||
INCLUDE common.inc
 | 
			
		||||
							
								
								
									
										19
									
								
								buildroot/share/PlatformIO/scripts/SAMD21_minitronics20.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								buildroot/share/PlatformIO/scripts/SAMD21_minitronics20.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
#
 | 
			
		||||
# SAMD21_minitronics20.py
 | 
			
		||||
# Customizations for env:SAMD21_minitronics20
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    from os.path import join, isfile
 | 
			
		||||
    import shutil
 | 
			
		||||
 | 
			
		||||
    Import("env")
 | 
			
		||||
 | 
			
		||||
    mf = env["MARLIN_FEATURES"]
 | 
			
		||||
    rxBuf = mf["RX_BUFFER_SIZE"] if "RX_BUFFER_SIZE" in mf else "0"
 | 
			
		||||
    txBuf = mf["TX_BUFFER_SIZE"] if "TX_BUFFER_SIZE" in mf else "0"
 | 
			
		||||
 | 
			
		||||
    serialBuf = str(max(int(rxBuf), int(txBuf), 350))
 | 
			
		||||
 | 
			
		||||
    build_flags = env.get('BUILD_FLAGS')
 | 
			
		||||
    env.Replace(BUILD_FLAGS=build_flags)
 | 
			
		||||
							
								
								
									
										20
									
								
								buildroot/share/PlatformIO/scripts/SAMD51_grandcentral_m4.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								buildroot/share/PlatformIO/scripts/SAMD51_grandcentral_m4.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
#
 | 
			
		||||
# SAMD51_grandcentral_m4.py
 | 
			
		||||
# Customizations for env:SAMD51_grandcentral_m4
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    from os.path import join, isfile
 | 
			
		||||
    import shutil
 | 
			
		||||
 | 
			
		||||
    Import("env")
 | 
			
		||||
 | 
			
		||||
    mf = env["MARLIN_FEATURES"]
 | 
			
		||||
    rxBuf = mf["RX_BUFFER_SIZE"] if "RX_BUFFER_SIZE" in mf else "0"
 | 
			
		||||
    txBuf = mf["TX_BUFFER_SIZE"] if "TX_BUFFER_SIZE" in mf else "0"
 | 
			
		||||
 | 
			
		||||
    serialBuf = str(max(int(rxBuf), int(txBuf), 350))
 | 
			
		||||
 | 
			
		||||
    build_flags = env.get('BUILD_FLAGS')
 | 
			
		||||
    build_flags.append("-DSERIAL_BUFFER_SIZE=" + serialBuf)
 | 
			
		||||
    env.Replace(BUILD_FLAGS=build_flags)
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/variants/STEVAL_F401VE/ldscript.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
@@ -1,59 +1,19 @@
 | 
			
		||||
try:
 | 
			
		||||
    import configparser
 | 
			
		||||
except ImportError:
 | 
			
		||||
    import ConfigParser as configparser
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
Import("env", "projenv")
 | 
			
		||||
# access to global build environment
 | 
			
		||||
print(env)
 | 
			
		||||
# access to project build environment (is used source files in "src" folder)
 | 
			
		||||
print(projenv)
 | 
			
		||||
 | 
			
		||||
config = configparser.ConfigParser()
 | 
			
		||||
config.read("platformio.ini")
 | 
			
		||||
 | 
			
		||||
#com_port = config.get("env:STM32F103RC_meeb", "upload_port")
 | 
			
		||||
#print('Use the {0:s} to reboot the board to dfu mode.'.format(com_port))
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Upload actions
 | 
			
		||||
# STM32F103RC_MEEB_3DP.py
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
 | 
			
		||||
def before_upload(source, target, env):
 | 
			
		||||
    print("before_upload")
 | 
			
		||||
    # do some actions
 | 
			
		||||
    # use com_port
 | 
			
		||||
    #
 | 
			
		||||
    env.Execute("pwd")
 | 
			
		||||
    Import("env", "projenv")
 | 
			
		||||
 | 
			
		||||
def after_upload(source, target, env):
 | 
			
		||||
    print("after_upload")
 | 
			
		||||
    # do some actions
 | 
			
		||||
    #
 | 
			
		||||
    #
 | 
			
		||||
    env.Execute("pwd")
 | 
			
		||||
    flash_size = 0
 | 
			
		||||
    vect_tab_addr = 0
 | 
			
		||||
 | 
			
		||||
print("Current build targets", map(str, BUILD_TARGETS))
 | 
			
		||||
    for define in env['CPPDEFINES']:
 | 
			
		||||
        if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
            vect_tab_addr = define[1]
 | 
			
		||||
        if define[0] == "STM32_FLASH_SIZE":
 | 
			
		||||
            flash_size = define[1]
 | 
			
		||||
 | 
			
		||||
env.AddPreAction("upload", before_upload)
 | 
			
		||||
env.AddPostAction("upload", after_upload)
 | 
			
		||||
 | 
			
		||||
flash_size = 0
 | 
			
		||||
vect_tab_addr = 0
 | 
			
		||||
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        vect_tab_addr = define[1]
 | 
			
		||||
    if define[0] == "STM32_FLASH_SIZE":
 | 
			
		||||
        flash_size = define[1]
 | 
			
		||||
 | 
			
		||||
print('Use the {0:s} address as the marlin app entry point.'.format(vect_tab_addr))
 | 
			
		||||
print('Use the {0:d}KB flash version of stm32f103rct6 chip.'.format(flash_size))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/STM32F103RC_MEEB_3DP.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
    print('Use the {0:s} address as the marlin app entry point.'.format(vect_tab_addr))
 | 
			
		||||
    print('Use the {0:d}KB flash version of stm32f103rct6 chip.'.format(flash_size))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
STM32_FLASH_SIZE = 256
 | 
			
		||||
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
    if define[0] == "STM32_FLASH_SIZE":
 | 
			
		||||
        STM32_FLASH_SIZE = define[1]
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08007000
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/STM32F103RC_SKR_MINI_" + str(STM32_FLASH_SIZE) + "K.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
@@ -1,36 +1,27 @@
 | 
			
		||||
import os
 | 
			
		||||
from os.path import join
 | 
			
		||||
from os.path import expandvars
 | 
			
		||||
Import("env")
 | 
			
		||||
#
 | 
			
		||||
# STM32F103RC_fysetc.py
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    from os.path import join
 | 
			
		||||
    from os.path import expandvars
 | 
			
		||||
    Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08008000
 | 
			
		||||
#for define in env['CPPDEFINES']:
 | 
			
		||||
#    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
#        env['CPPDEFINES'].remove(define)
 | 
			
		||||
#env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08008000"))
 | 
			
		||||
    # Custom HEX from ELF
 | 
			
		||||
    env.AddPostAction(
 | 
			
		||||
        join("$BUILD_DIR", "${PROGNAME}.elf"),
 | 
			
		||||
        env.VerboseAction(" ".join([
 | 
			
		||||
            "$OBJCOPY", "-O ihex", "$TARGET",
 | 
			
		||||
            "\"" + join("$BUILD_DIR", "${PROGNAME}.hex") + "\"", # Note: $BUILD_DIR is a full path
 | 
			
		||||
        ]), "Building $TARGET"))
 | 
			
		||||
 | 
			
		||||
#custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/fysetc_stm32f103rc.ld")
 | 
			
		||||
#for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
#    if "-Wl,-T" in flag:
 | 
			
		||||
#        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
#    elif flag == "-T":
 | 
			
		||||
#        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
    # In-line command with arguments
 | 
			
		||||
    UPLOAD_TOOL="stm32flash"
 | 
			
		||||
    platform = env.PioPlatform()
 | 
			
		||||
    if platform.get_package_dir("tool-stm32duino") != None:
 | 
			
		||||
        UPLOAD_TOOL=expandvars("\"" + join(platform.get_package_dir("tool-stm32duino"),"stm32flash","stm32flash") + "\"")
 | 
			
		||||
 | 
			
		||||
# Custom HEX from ELF
 | 
			
		||||
env.AddPostAction(
 | 
			
		||||
	join("$BUILD_DIR","${PROGNAME}.elf"),
 | 
			
		||||
	env.VerboseAction(" ".join([
 | 
			
		||||
		"$OBJCOPY", "-O ihex", "$TARGET", # TARGET=.pio/build/fysetc_STM32F1/firmware.elf
 | 
			
		||||
		"\"" + join("$BUILD_DIR","${PROGNAME}.hex") + "\"", # Note: $BUILD_DIR is a full path
 | 
			
		||||
	]), "Building $TARGET"))
 | 
			
		||||
 | 
			
		||||
# In-line command with arguments
 | 
			
		||||
UPLOAD_TOOL="stm32flash"
 | 
			
		||||
platform = env.PioPlatform()
 | 
			
		||||
if platform.get_package_dir("tool-stm32duino") != None:
 | 
			
		||||
	UPLOAD_TOOL=expandvars("\"" + join(platform.get_package_dir("tool-stm32duino"),"stm32flash","stm32flash") + "\"")
 | 
			
		||||
 | 
			
		||||
env.Replace(
 | 
			
		||||
	UPLOADER=UPLOAD_TOOL,
 | 
			
		||||
	UPLOADCMD=expandvars(UPLOAD_TOOL + " -v -i rts,-dtr,dtr -R -b 115200 -g 0x8000000 -w \"" + join("$BUILD_DIR","${PROGNAME}.hex")+"\"" + " $UPLOAD_PORT")
 | 
			
		||||
)
 | 
			
		||||
    env.Replace(
 | 
			
		||||
        UPLOADER=UPLOAD_TOOL,
 | 
			
		||||
        UPLOADCMD=expandvars(UPLOAD_TOOL + " -v -i rts,-dtr,dtr -R -b 115200 -g 0x8000000 -w \"" + join("$BUILD_DIR","${PROGNAME}.hex")+"\"" + " $UPLOAD_PORT")
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08007000
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/STM32F103RE_SKR_E3_DIP.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
@@ -1,33 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08010000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08010000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/STM32F103VE_longer.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Rename ${PROGNAME}.bin and save it as 'project.bin' (No encryption on the Longer3D)
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    marlin_alfa = open(target[0].dir.path +'/project.bin', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = firmware.read(1)
 | 
			
		||||
            marlin_alfa.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        firmware.close()
 | 
			
		||||
        marlin_alfa.close()
 | 
			
		||||
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
@@ -1,34 +1,31 @@
 | 
			
		||||
import os,shutil
 | 
			
		||||
from SCons.Script import DefaultEnvironment
 | 
			
		||||
from platformio import util
 | 
			
		||||
#
 | 
			
		||||
# STM32F1_create_variant.py
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    import shutil,marlin
 | 
			
		||||
    from pathlib import Path
 | 
			
		||||
 | 
			
		||||
def copytree(src, dst, symlinks=False, ignore=None):
 | 
			
		||||
    for item in os.listdir(src):
 | 
			
		||||
        s = os.path.join(src, item)
 | 
			
		||||
        d = os.path.join(dst, item)
 | 
			
		||||
        if os.path.isdir(s):
 | 
			
		||||
            shutil.copytree(s, d, symlinks, ignore)
 | 
			
		||||
        else:
 | 
			
		||||
            shutil.copy2(s, d)
 | 
			
		||||
    Import("env")
 | 
			
		||||
    platform = env.PioPlatform()
 | 
			
		||||
    board = env.BoardConfig()
 | 
			
		||||
 | 
			
		||||
env = DefaultEnvironment()
 | 
			
		||||
platform = env.PioPlatform()
 | 
			
		||||
board = env.BoardConfig()
 | 
			
		||||
    FRAMEWORK_DIR = Path(platform.get_package_dir("framework-arduinoststm32-maple"))
 | 
			
		||||
    assert FRAMEWORK_DIR.is_dir()
 | 
			
		||||
 | 
			
		||||
FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoststm32-maple")
 | 
			
		||||
assert os.path.isdir(FRAMEWORK_DIR)
 | 
			
		||||
assert os.path.isdir("buildroot/share/PlatformIO/variants")
 | 
			
		||||
    source_root = Path("buildroot/share/PlatformIO/variants")
 | 
			
		||||
    assert source_root.is_dir()
 | 
			
		||||
 | 
			
		||||
variant = board.get("build.variant")
 | 
			
		||||
variant_dir = os.path.join(FRAMEWORK_DIR, "STM32F1", "variants", variant)
 | 
			
		||||
    variant = board.get("build.variant")
 | 
			
		||||
    variant_dir = FRAMEWORK_DIR / "STM32F1/variants" / variant
 | 
			
		||||
 | 
			
		||||
source_dir = os.path.join("buildroot/share/PlatformIO/variants", variant)
 | 
			
		||||
assert os.path.isdir(source_dir)
 | 
			
		||||
    source_dir = source_root / variant
 | 
			
		||||
    assert source_dir.is_dir()
 | 
			
		||||
 | 
			
		||||
if os.path.isdir(variant_dir):
 | 
			
		||||
    shutil.rmtree(variant_dir)
 | 
			
		||||
    if variant_dir.is_dir():
 | 
			
		||||
        shutil.rmtree(variant_dir)
 | 
			
		||||
 | 
			
		||||
if not os.path.isdir(variant_dir):
 | 
			
		||||
    os.mkdir(variant_dir)
 | 
			
		||||
    if not variant_dir.is_dir():
 | 
			
		||||
        variant_dir.mkdir()
 | 
			
		||||
 | 
			
		||||
copytree(source_dir, variant_dir)
 | 
			
		||||
    marlin.copytree(source_dir, variant_dir)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										0
									
								
								buildroot/share/PlatformIO/scripts/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								buildroot/share/PlatformIO/scripts/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										6
									
								
								buildroot/share/PlatformIO/scripts/add_nanolib.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								buildroot/share/PlatformIO/scripts/add_nanolib.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
#
 | 
			
		||||
# add_nanolib.py
 | 
			
		||||
#
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
env.Append(LINKFLAGS=["--specs=nano.specs"])
 | 
			
		||||
@@ -1,127 +1,126 @@
 | 
			
		||||
Import("env")
 | 
			
		||||
import os
 | 
			
		||||
import random
 | 
			
		||||
import struct
 | 
			
		||||
import uuid
 | 
			
		||||
#
 | 
			
		||||
# chitu_crypt.py
 | 
			
		||||
# Customizations for Chitu boards
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    import struct,uuid,marlin
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08008800
 | 
			
		||||
env['CPPDEFINES'].remove(("VECT_TAB_ADDR", "0x8000000"))
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08008800"))
 | 
			
		||||
    board = marlin.env.BoardConfig()
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/chitu_f103.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
    def calculate_crc(contents, seed):
 | 
			
		||||
        accumulating_xor_value = seed;
 | 
			
		||||
 | 
			
		||||
        for i in range(0, len(contents), 4):
 | 
			
		||||
            value = struct.unpack('<I', contents[ i : i + 4])[0]
 | 
			
		||||
            accumulating_xor_value = accumulating_xor_value ^ value
 | 
			
		||||
        return accumulating_xor_value
 | 
			
		||||
 | 
			
		||||
def calculate_crc(contents, seed):
 | 
			
		||||
    accumulating_xor_value = seed;
 | 
			
		||||
    def xor_block(r0, r1, block_number, block_size, file_key):
 | 
			
		||||
        # This is the loop counter
 | 
			
		||||
        loop_counter = 0x0
 | 
			
		||||
 | 
			
		||||
    for i in range(0, len(contents), 4):
 | 
			
		||||
        value = struct.unpack('<I', contents[ i : i + 4])[0]
 | 
			
		||||
        accumulating_xor_value = accumulating_xor_value ^ value
 | 
			
		||||
    return accumulating_xor_value
 | 
			
		||||
        # This is the key length
 | 
			
		||||
        key_length = 0x18
 | 
			
		||||
 | 
			
		||||
def xor_block(r0, r1, block_number, block_size, file_key):
 | 
			
		||||
    # This is the loop counter
 | 
			
		||||
    loop_counter = 0x0
 | 
			
		||||
        # This is an initial seed
 | 
			
		||||
        xor_seed = 0x4BAD
 | 
			
		||||
 | 
			
		||||
    # This is the key length
 | 
			
		||||
    key_length = 0x18
 | 
			
		||||
        # This is the block counter
 | 
			
		||||
        block_number = xor_seed * block_number
 | 
			
		||||
 | 
			
		||||
    # This is an initial seed
 | 
			
		||||
    xor_seed = 0x4BAD
 | 
			
		||||
        #load the xor key from the file
 | 
			
		||||
        r7 =  file_key
 | 
			
		||||
 | 
			
		||||
    # This is the block counter
 | 
			
		||||
    block_number = xor_seed * block_number
 | 
			
		||||
        for loop_counter in range(0, block_size):
 | 
			
		||||
            # meant to make sure different bits of the key are used.
 | 
			
		||||
            xor_seed = int(loop_counter / key_length)
 | 
			
		||||
 | 
			
		||||
    #load the xor key from the file
 | 
			
		||||
    r7 =  file_key
 | 
			
		||||
            # IP is a scratch register / R12
 | 
			
		||||
            ip = loop_counter - (key_length * xor_seed)
 | 
			
		||||
 | 
			
		||||
    for loop_counter in range(0, block_size):
 | 
			
		||||
        # meant to make sure different bits of the key are used.
 | 
			
		||||
        xor_seed = int(loop_counter/key_length)
 | 
			
		||||
            # xor_seed = (loop_counter * loop_counter) + block_number
 | 
			
		||||
            xor_seed = (loop_counter * loop_counter) + block_number
 | 
			
		||||
 | 
			
		||||
        # IP is a scratch register / R12
 | 
			
		||||
        ip = loop_counter - (key_length * xor_seed)
 | 
			
		||||
            # shift the xor_seed left by the bits in IP.
 | 
			
		||||
            xor_seed = xor_seed >> ip
 | 
			
		||||
 | 
			
		||||
        # xor_seed = (loop_counter * loop_counter) + block_number
 | 
			
		||||
        xor_seed = (loop_counter * loop_counter) + block_number
 | 
			
		||||
            # load a byte into IP
 | 
			
		||||
            ip = r0[loop_counter]
 | 
			
		||||
 | 
			
		||||
        # shift the xor_seed left by the bits in IP.
 | 
			
		||||
        xor_seed = xor_seed >> ip
 | 
			
		||||
            # XOR the seed with r7
 | 
			
		||||
            xor_seed = xor_seed ^ r7
 | 
			
		||||
 | 
			
		||||
        # load a byte into IP
 | 
			
		||||
        ip = r0[loop_counter]
 | 
			
		||||
            # and then with IP
 | 
			
		||||
            xor_seed = xor_seed ^ ip
 | 
			
		||||
 | 
			
		||||
        # XOR the seed with r7
 | 
			
		||||
        xor_seed = xor_seed ^ r7
 | 
			
		||||
            #Now store the byte back
 | 
			
		||||
            r1[loop_counter] = xor_seed & 0xFF
 | 
			
		||||
 | 
			
		||||
        # and then with IP
 | 
			
		||||
        xor_seed = xor_seed ^ ip
 | 
			
		||||
            #increment the loop_counter
 | 
			
		||||
            loop_counter = loop_counter + 1
 | 
			
		||||
 | 
			
		||||
        #Now store the byte back
 | 
			
		||||
        r1[loop_counter] = xor_seed & 0xFF
 | 
			
		||||
    def encrypt_file(input, output_file, file_length):
 | 
			
		||||
        input_file = bytearray(input.read())
 | 
			
		||||
        block_size = 0x800
 | 
			
		||||
        key_length = 0x18
 | 
			
		||||
 | 
			
		||||
        #increment the loop_counter
 | 
			
		||||
        loop_counter = loop_counter + 1
 | 
			
		||||
        uid_value = uuid.uuid4()
 | 
			
		||||
        file_key = int(uid_value.hex[0:8], 16)
 | 
			
		||||
 | 
			
		||||
        xor_crc = 0xEF3D4323;
 | 
			
		||||
 | 
			
		||||
def encrypt_file(input, output_file, file_length):
 | 
			
		||||
    input_file = bytearray(input.read())
 | 
			
		||||
    block_size = 0x800
 | 
			
		||||
    key_length = 0x18
 | 
			
		||||
        # the input file is exepcted to be in chunks of 0x800
 | 
			
		||||
        # so round the size
 | 
			
		||||
        while len(input_file) % block_size != 0:
 | 
			
		||||
            input_file.extend(b'0x0')
 | 
			
		||||
 | 
			
		||||
    uid_value = uuid.uuid4()
 | 
			
		||||
    file_key = int(uid_value.hex[0:8], 16)
 | 
			
		||||
        # write the file header
 | 
			
		||||
        output_file.write(struct.pack(">I", 0x443D2D3F))
 | 
			
		||||
        # encrypt the contents using a known file header key
 | 
			
		||||
 | 
			
		||||
    xor_crc = 0xEF3D4323;
 | 
			
		||||
        # write the file_key
 | 
			
		||||
        output_file.write(struct.pack("<I", file_key))
 | 
			
		||||
 | 
			
		||||
    # the input file is exepcted to be in chunks of 0x800
 | 
			
		||||
    # so round the size
 | 
			
		||||
    while len(input_file) % block_size != 0:
 | 
			
		||||
        input_file.extend(b'0x0')
 | 
			
		||||
        #TODO - how to enforce that the firmware aligns to block boundaries?
 | 
			
		||||
        block_count = int(len(input_file) / block_size)
 | 
			
		||||
        print ("Block Count is ", block_count)
 | 
			
		||||
        for block_number in range(0, block_count):
 | 
			
		||||
            block_offset = (block_number * block_size)
 | 
			
		||||
            block_end = block_offset + block_size
 | 
			
		||||
            block_array = bytearray(input_file[block_offset: block_end])
 | 
			
		||||
            xor_block(block_array, block_array, block_number, block_size, file_key)
 | 
			
		||||
            for n in range (0, block_size):
 | 
			
		||||
                input_file[block_offset + n] = block_array[n]
 | 
			
		||||
 | 
			
		||||
    # write the file header
 | 
			
		||||
    output_file.write(struct.pack(">I", 0x443D2D3F))
 | 
			
		||||
    # encrypt the contents using a known file header key
 | 
			
		||||
            # update the expected CRC value.
 | 
			
		||||
            xor_crc = calculate_crc(block_array, xor_crc)
 | 
			
		||||
 | 
			
		||||
    # write the file_key
 | 
			
		||||
    output_file.write(struct.pack("<I", file_key))
 | 
			
		||||
        # write CRC
 | 
			
		||||
        output_file.write(struct.pack("<I", xor_crc))
 | 
			
		||||
 | 
			
		||||
    #TODO - how to enforce that the firmware aligns to block boundaries?
 | 
			
		||||
    block_count = int(len(input_file) / block_size)
 | 
			
		||||
    print ("Block Count is ", block_count)
 | 
			
		||||
    for block_number in range(0, block_count):
 | 
			
		||||
        block_offset = (block_number * block_size)
 | 
			
		||||
        block_end = block_offset + block_size
 | 
			
		||||
        block_array = bytearray(input_file[block_offset: block_end])
 | 
			
		||||
        xor_block(block_array, block_array, block_number, block_size, file_key)
 | 
			
		||||
        for n in range (0, block_size):
 | 
			
		||||
            input_file[block_offset + n] = block_array[n]
 | 
			
		||||
        # finally, append the encrypted results.
 | 
			
		||||
        output_file.write(input_file)
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
        # update the expected CRC value.
 | 
			
		||||
        xor_crc = calculate_crc(block_array, xor_crc)
 | 
			
		||||
    # Encrypt ${PROGNAME}.bin and save it as 'update.cbd'
 | 
			
		||||
    def encrypt(source, target, env):
 | 
			
		||||
        from pathlib import Path
 | 
			
		||||
 | 
			
		||||
    # write CRC
 | 
			
		||||
    output_file.write(struct.pack("<I", xor_crc))
 | 
			
		||||
        fwpath = Path(target[0].path)
 | 
			
		||||
        fwsize = fwpath.stat().st_size
 | 
			
		||||
 | 
			
		||||
    # finally, append the encrypted results.
 | 
			
		||||
    output_file.write(input_file)
 | 
			
		||||
    return
 | 
			
		||||
        enname = board.get("build.crypt_chitu")
 | 
			
		||||
        enpath = Path(target[0].dir.path)
 | 
			
		||||
 | 
			
		||||
        fwfile = fwpath.open("rb")
 | 
			
		||||
        enfile = (enpath / enname).open("wb")
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as 'update.cbd'
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    update = open(target[0].dir.path +'/update.cbd', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
        print(f"Encrypting {fwpath} to {enname}")
 | 
			
		||||
        encrypt_file(fwfile, enfile, fwsize)
 | 
			
		||||
        fwfile.close()
 | 
			
		||||
        enfile.close()
 | 
			
		||||
        fwpath.unlink()
 | 
			
		||||
 | 
			
		||||
    encrypt_file(firmware, update, length)
 | 
			
		||||
 | 
			
		||||
    firmware.close()
 | 
			
		||||
    update.close()
 | 
			
		||||
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
    marlin.relocate_firmware("0x08008800")
 | 
			
		||||
    marlin.add_post_action(encrypt);
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,45 @@
 | 
			
		||||
# common-cxxflags.py
 | 
			
		||||
# Convenience script to apply customizations to CPP flags
 | 
			
		||||
#
 | 
			
		||||
Import("env")
 | 
			
		||||
env.Append(CXXFLAGS=[
 | 
			
		||||
  "-Wno-register"
 | 
			
		||||
  #"-Wno-incompatible-pointer-types",
 | 
			
		||||
  #"-Wno-unused-const-variable",
 | 
			
		||||
  #"-Wno-maybe-uninitialized",
 | 
			
		||||
  #"-Wno-sign-compare"
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    Import("env")
 | 
			
		||||
 | 
			
		||||
    cxxflags = [
 | 
			
		||||
        # "-Wno-incompatible-pointer-types",
 | 
			
		||||
        # "-Wno-unused-const-variable",
 | 
			
		||||
        # "-Wno-maybe-uninitialized",
 | 
			
		||||
        # "-Wno-sign-compare"
 | 
			
		||||
    ]
 | 
			
		||||
    if "teensy" not in env["PIOENV"]:
 | 
			
		||||
        cxxflags += ["-Wno-register"]
 | 
			
		||||
    env.Append(CXXFLAGS=cxxflags)
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Add CPU frequency as a compile time constant instead of a runtime variable
 | 
			
		||||
    #
 | 
			
		||||
    def add_cpu_freq():
 | 
			
		||||
        if "BOARD_F_CPU" in env:
 | 
			
		||||
            env["BUILD_FLAGS"].append("-DBOARD_F_CPU=" + env["BOARD_F_CPU"])
 | 
			
		||||
 | 
			
		||||
    # Useful for JTAG debugging
 | 
			
		||||
    #
 | 
			
		||||
    # It will separate release and debug build folders.
 | 
			
		||||
    # It useful to keep two live versions: a debug version for debugging and another for
 | 
			
		||||
    # release, for flashing when upload is not done automatically by jlink/stlink.
 | 
			
		||||
    # Without this, PIO needs to recompile everything twice for any small change.
 | 
			
		||||
    if env.GetBuildType() == "debug" and env.get("UPLOAD_PROTOCOL") not in ["jlink", "stlink", "custom"]:
 | 
			
		||||
        env["BUILD_DIR"] = "$PROJECT_BUILD_DIR/$PIOENV/debug"
 | 
			
		||||
 | 
			
		||||
        def on_program_ready(source, target, env):
 | 
			
		||||
            import shutil
 | 
			
		||||
            shutil.copy(target[0].get_abspath(), env.subst("$PROJECT_BUILD_DIR/$PIOENV"))
 | 
			
		||||
 | 
			
		||||
        env.AddPostAction("$PROGPATH", on_program_ready)
 | 
			
		||||
 | 
			
		||||
    # On some platform, F_CPU is a runtime variable. Since it's used to convert from ns
 | 
			
		||||
    # to CPU cycles, this adds overhead preventing small delay (in the order of less than
 | 
			
		||||
    # 30 cycles) to be generated correctly. By using a compile time constant instead
 | 
			
		||||
    # the compiler will perform the computation and this overhead will be avoided
 | 
			
		||||
    add_cpu_freq()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,16 @@
 | 
			
		||||
#
 | 
			
		||||
# common-dependencies-post.py
 | 
			
		||||
# post:common-dependencies-post.py
 | 
			
		||||
# Convenience script to add build flags for Marlin Enabled Features
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    Import("env", "projenv")
 | 
			
		||||
 | 
			
		||||
Import("env")
 | 
			
		||||
Import("projenv")
 | 
			
		||||
    def apply_board_build_flags():
 | 
			
		||||
        if not 'BOARD_CUSTOM_BUILD_FLAGS' in env['MARLIN_FEATURES']:
 | 
			
		||||
            return
 | 
			
		||||
        projenv.Append(CCFLAGS=env['MARLIN_FEATURES']['BOARD_CUSTOM_BUILD_FLAGS'].split())
 | 
			
		||||
 | 
			
		||||
def apply_board_build_flags():
 | 
			
		||||
	if not 'BOARD_CUSTOM_BUILD_FLAGS' in env['MARLIN_FEATURES']:
 | 
			
		||||
		return
 | 
			
		||||
	projenv.Append(CCFLAGS=env['MARLIN_FEATURES']['BOARD_CUSTOM_BUILD_FLAGS'].split())
 | 
			
		||||
 | 
			
		||||
# We need to add the board build flags in a post script
 | 
			
		||||
# so the platform build script doesn't overwrite the custom CCFLAGS
 | 
			
		||||
apply_board_build_flags()
 | 
			
		||||
    # We need to add the board build flags in a post script
 | 
			
		||||
    # so the platform build script doesn't overwrite the custom CCFLAGS
 | 
			
		||||
    apply_board_build_flags()
 | 
			
		||||
 
 | 
			
		||||
@@ -26,8 +26,6 @@
 | 
			
		||||
 * Used by common-dependencies.py
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define NUM_SERIAL 1 // Normally provided by HAL/HAL.h
 | 
			
		||||
 | 
			
		||||
#include "../../../../Marlin/src/inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
@@ -37,7 +35,9 @@
 | 
			
		||||
  // Feature checks for SR_LCD_3W_NL
 | 
			
		||||
#elif EITHER(LCD_I2C_TYPE_MCP23017, LCD_I2C_TYPE_MCP23008)
 | 
			
		||||
  #define USES_LIQUIDTWI2
 | 
			
		||||
#elif ANY(HAS_MARLINUI_HD44780, LCD_I2C_TYPE_PCF8575, LCD_I2C_TYPE_PCA8574, SR_LCD_2W_NL, LCM1602)
 | 
			
		||||
#elif ENABLED(LCD_I2C_TYPE_PCA8574)
 | 
			
		||||
  #define USES_LIQUIDCRYSTAL_I2C
 | 
			
		||||
#elif ANY(HAS_MARLINUI_HD44780, LCD_I2C_TYPE_PCF8575, SR_LCD_2W_NL, LCM1602)
 | 
			
		||||
  #define USES_LIQUIDCRYSTAL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -45,31 +45,20 @@
 | 
			
		||||
  #define HAS_SAVED_POSITIONS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ENABLED(HOST_PROMPT_SUPPORT) && DISABLED(EMERGENCY_PARSER)
 | 
			
		||||
  #define HAS_GCODE_M876
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if EXTRUDERS
 | 
			
		||||
  #define HAS_EXTRUDERS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ENABLED(DUET_SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
 | 
			
		||||
  #define HAS_SMART_EFF_MOD
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if HAS_LCD_MENU
 | 
			
		||||
#if HAS_MARLINUI_MENU
 | 
			
		||||
  #if ENABLED(BACKLASH_GCODE)
 | 
			
		||||
    #define HAS_MENU_BACKLASH
 | 
			
		||||
  #endif
 | 
			
		||||
  #if ENABLED(LEVEL_BED_CORNERS)
 | 
			
		||||
  #if ENABLED(LCD_BED_TRAMMING)
 | 
			
		||||
    #define HAS_MENU_BED_CORNERS
 | 
			
		||||
  #endif
 | 
			
		||||
  #if ENABLED(CANCEL_OBJECTS)
 | 
			
		||||
    #define HAS_MENU_CANCELOBJECT
 | 
			
		||||
  #endif
 | 
			
		||||
  #if ENABLED(CUSTOM_USER_MENUS)
 | 
			
		||||
    #define HAS_MENU_CUSTOM
 | 
			
		||||
  #endif
 | 
			
		||||
  #if EITHER(DELTA_CALIBRATION_MENU, DELTA_AUTO_CALIBRATION)
 | 
			
		||||
    #define HAS_MENU_DELTA_CALIBRATE
 | 
			
		||||
  #endif
 | 
			
		||||
@@ -109,6 +98,9 @@
 | 
			
		||||
  #if ENABLED(TOUCH_SCREEN_CALIBRATION)
 | 
			
		||||
    #define HAS_MENU_TOUCH_SCREEN
 | 
			
		||||
  #endif
 | 
			
		||||
  #if ENABLED(ASSISTED_TRAMMING_WIZARD)
 | 
			
		||||
    #define HAS_MENU_TRAMMING
 | 
			
		||||
  #endif
 | 
			
		||||
  #if ENABLED(AUTO_BED_LEVELING_UBL)
 | 
			
		||||
    #define HAS_MENU_UBL
 | 
			
		||||
  #endif
 | 
			
		||||
 
 | 
			
		||||
@@ -2,286 +2,250 @@
 | 
			
		||||
# common-dependencies.py
 | 
			
		||||
# Convenience script to check dependencies and add libs and sources for Marlin Enabled Features
 | 
			
		||||
#
 | 
			
		||||
import subprocess
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
try:
 | 
			
		||||
	import configparser
 | 
			
		||||
except ImportError:
 | 
			
		||||
	import ConfigParser as configparser
 | 
			
		||||
try:
 | 
			
		||||
	# PIO < 4.4
 | 
			
		||||
	from platformio.managers.package import PackageManager
 | 
			
		||||
except ImportError:
 | 
			
		||||
	# PIO >= 4.4
 | 
			
		||||
	from platformio.package.meta import PackageSpec as PackageManager
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
 | 
			
		||||
Import("env")
 | 
			
		||||
    import subprocess,os,re
 | 
			
		||||
    Import("env")
 | 
			
		||||
 | 
			
		||||
#print(env.Dump())
 | 
			
		||||
    from platformio.package.meta import PackageSpec
 | 
			
		||||
    from platformio.project.config import ProjectConfig
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
	verbose = int(env.GetProjectOption('custom_verbose'))
 | 
			
		||||
except:
 | 
			
		||||
	verbose = 0
 | 
			
		||||
    verbose = 0
 | 
			
		||||
    FEATURE_CONFIG = {}
 | 
			
		||||
 | 
			
		||||
def blab(str):
 | 
			
		||||
	if verbose:
 | 
			
		||||
		print(str)
 | 
			
		||||
    def validate_pio():
 | 
			
		||||
        PIO_VERSION_MIN = (6, 0, 1)
 | 
			
		||||
        try:
 | 
			
		||||
            from platformio import VERSION as PIO_VERSION
 | 
			
		||||
            weights = (1000, 100, 1)
 | 
			
		||||
            version_min = sum([x[0] * float(re.sub(r'[^0-9]', '.', str(x[1]))) for x in zip(weights, PIO_VERSION_MIN)])
 | 
			
		||||
            version_cur = sum([x[0] * float(re.sub(r'[^0-9]', '.', str(x[1]))) for x in zip(weights, PIO_VERSION)])
 | 
			
		||||
            if version_cur < version_min:
 | 
			
		||||
                print()
 | 
			
		||||
                print("**************************************************")
 | 
			
		||||
                print("******      An update to PlatformIO is      ******")
 | 
			
		||||
                print("******  required to build Marlin Firmware.  ******")
 | 
			
		||||
                print("******                                      ******")
 | 
			
		||||
                print("******      Minimum version: ", PIO_VERSION_MIN, "    ******")
 | 
			
		||||
                print("******      Current Version: ", PIO_VERSION, "    ******")
 | 
			
		||||
                print("******                                      ******")
 | 
			
		||||
                print("******   Update PlatformIO and try again.   ******")
 | 
			
		||||
                print("**************************************************")
 | 
			
		||||
                print()
 | 
			
		||||
                exit(1)
 | 
			
		||||
        except SystemExit:
 | 
			
		||||
            exit(1)
 | 
			
		||||
        except:
 | 
			
		||||
            print("Can't detect PlatformIO Version")
 | 
			
		||||
 | 
			
		||||
def parse_pkg_uri(spec):
 | 
			
		||||
	if PackageManager.__name__ == 'PackageSpec':
 | 
			
		||||
		return PackageManager(spec).name
 | 
			
		||||
	else:
 | 
			
		||||
		name, _, _ = PackageManager.parse_pkg_uri(spec)
 | 
			
		||||
		return name
 | 
			
		||||
    def blab(str,level=1):
 | 
			
		||||
        if verbose >= level:
 | 
			
		||||
            print("[deps] %s" % str)
 | 
			
		||||
 | 
			
		||||
FEATURE_CONFIG = {}
 | 
			
		||||
    def add_to_feat_cnf(feature, flines):
 | 
			
		||||
 | 
			
		||||
def add_to_feat_cnf(feature, flines):
 | 
			
		||||
        try:
 | 
			
		||||
            feat = FEATURE_CONFIG[feature]
 | 
			
		||||
        except:
 | 
			
		||||
            FEATURE_CONFIG[feature] = {}
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		feat = FEATURE_CONFIG[feature]
 | 
			
		||||
	except:
 | 
			
		||||
		FEATURE_CONFIG[feature] = {}
 | 
			
		||||
        # Get a reference to the FEATURE_CONFIG under construction
 | 
			
		||||
        feat = FEATURE_CONFIG[feature]
 | 
			
		||||
 | 
			
		||||
	feat = FEATURE_CONFIG[feature]
 | 
			
		||||
	atoms = re.sub(',\\s*', '\n', flines).strip().split('\n')
 | 
			
		||||
	for dep in atoms:
 | 
			
		||||
		parts = dep.split('=')
 | 
			
		||||
		name = parts.pop(0)
 | 
			
		||||
		rest = '='.join(parts)
 | 
			
		||||
		if name in ['extra_scripts', 'src_filter', 'lib_ignore']:
 | 
			
		||||
			feat[name] = rest
 | 
			
		||||
		else:
 | 
			
		||||
			feat['lib_deps'] += [dep]
 | 
			
		||||
        # Split up passed lines on commas or newlines and iterate
 | 
			
		||||
        # Add common options to the features config under construction
 | 
			
		||||
        # For lib_deps replace a previous instance of the same library
 | 
			
		||||
        atoms = re.sub(r',\s*', '\n', flines).strip().split('\n')
 | 
			
		||||
        for line in atoms:
 | 
			
		||||
            parts = line.split('=')
 | 
			
		||||
            name = parts.pop(0)
 | 
			
		||||
            if name in ['build_flags', 'extra_scripts', 'src_filter', 'lib_ignore']:
 | 
			
		||||
                feat[name] = '='.join(parts)
 | 
			
		||||
                blab("[%s] %s=%s" % (feature, name, feat[name]), 3)
 | 
			
		||||
            else:
 | 
			
		||||
                for dep in re.split(r',\s*', line):
 | 
			
		||||
                    lib_name = re.sub(r'@([~^]|[<>]=?)?[\d.]+', '', dep.strip()).split('=').pop(0)
 | 
			
		||||
                    lib_re = re.compile('(?!^' + lib_name + '\\b)')
 | 
			
		||||
                    feat['lib_deps'] = list(filter(lib_re.match, feat['lib_deps'])) + [dep]
 | 
			
		||||
                    blab("[%s] lib_deps = %s" % (feature, dep), 3)
 | 
			
		||||
 | 
			
		||||
def load_config():
 | 
			
		||||
	config = configparser.ConfigParser()
 | 
			
		||||
	config.read("platformio.ini")
 | 
			
		||||
	items = config.items('features')
 | 
			
		||||
	for key in items:
 | 
			
		||||
		feature = key[0].upper()
 | 
			
		||||
		if not feature in FEATURE_CONFIG:
 | 
			
		||||
			FEATURE_CONFIG[feature] = { 'lib_deps': [] }
 | 
			
		||||
		add_to_feat_cnf(feature, key[1])
 | 
			
		||||
    def load_features():
 | 
			
		||||
        blab("========== Gather [features] entries...")
 | 
			
		||||
        for key in ProjectConfig().items('features'):
 | 
			
		||||
            feature = key[0].upper()
 | 
			
		||||
            if not feature in FEATURE_CONFIG:
 | 
			
		||||
                FEATURE_CONFIG[feature] = { 'lib_deps': [] }
 | 
			
		||||
            add_to_feat_cnf(feature, key[1])
 | 
			
		||||
 | 
			
		||||
	# Add options matching custom_marlin.MY_OPTION to the pile
 | 
			
		||||
	all_opts = env.GetProjectOptions()
 | 
			
		||||
	for n in all_opts:
 | 
			
		||||
		mat = re.match(r'custom_marlin\.(.+)', n[0])
 | 
			
		||||
		if mat:
 | 
			
		||||
			try:
 | 
			
		||||
				val = env.GetProjectOption(n[0])
 | 
			
		||||
			except:
 | 
			
		||||
				val = None
 | 
			
		||||
			if val:
 | 
			
		||||
				add_to_feat_cnf(mat.group(1).upper(), val)
 | 
			
		||||
        # Add options matching custom_marlin.MY_OPTION to the pile
 | 
			
		||||
        blab("========== Gather custom_marlin entries...")
 | 
			
		||||
        for n in env.GetProjectOptions():
 | 
			
		||||
            key = n[0]
 | 
			
		||||
            mat = re.match(r'custom_marlin\.(.+)', key)
 | 
			
		||||
            if mat:
 | 
			
		||||
                try:
 | 
			
		||||
                    val = env.GetProjectOption(key)
 | 
			
		||||
                except:
 | 
			
		||||
                    val = None
 | 
			
		||||
                if val:
 | 
			
		||||
                    opt = mat[1].upper()
 | 
			
		||||
                    blab("%s.custom_marlin.%s = '%s'" % ( env['PIOENV'], opt, val ))
 | 
			
		||||
                    add_to_feat_cnf(opt, val)
 | 
			
		||||
 | 
			
		||||
def get_all_known_libs():
 | 
			
		||||
	known_libs = []
 | 
			
		||||
	for feature in FEATURE_CONFIG:
 | 
			
		||||
		feat = FEATURE_CONFIG[feature]
 | 
			
		||||
		if not 'lib_deps' in feat:
 | 
			
		||||
			continue
 | 
			
		||||
		for dep in feat['lib_deps']:
 | 
			
		||||
			name = parse_pkg_uri(dep)
 | 
			
		||||
			known_libs.append(name)
 | 
			
		||||
	return known_libs
 | 
			
		||||
    def get_all_known_libs():
 | 
			
		||||
        known_libs = []
 | 
			
		||||
        for feature in FEATURE_CONFIG:
 | 
			
		||||
            feat = FEATURE_CONFIG[feature]
 | 
			
		||||
            if not 'lib_deps' in feat:
 | 
			
		||||
                continue
 | 
			
		||||
            for dep in feat['lib_deps']:
 | 
			
		||||
                known_libs.append(PackageSpec(dep).name)
 | 
			
		||||
        return known_libs
 | 
			
		||||
 | 
			
		||||
def get_all_env_libs():
 | 
			
		||||
	env_libs = []
 | 
			
		||||
	lib_deps = env.GetProjectOption('lib_deps')
 | 
			
		||||
	for dep in lib_deps:
 | 
			
		||||
		name = parse_pkg_uri(dep)
 | 
			
		||||
		env_libs.append(name)
 | 
			
		||||
	return env_libs
 | 
			
		||||
    def get_all_env_libs():
 | 
			
		||||
        env_libs = []
 | 
			
		||||
        lib_deps = env.GetProjectOption('lib_deps')
 | 
			
		||||
        for dep in lib_deps:
 | 
			
		||||
            env_libs.append(PackageSpec(dep).name)
 | 
			
		||||
        return env_libs
 | 
			
		||||
 | 
			
		||||
def set_env_field(field, value):
 | 
			
		||||
	proj = env.GetProjectConfig()
 | 
			
		||||
	proj.set("env:" + env['PIOENV'], field, value)
 | 
			
		||||
    def set_env_field(field, value):
 | 
			
		||||
        proj = env.GetProjectConfig()
 | 
			
		||||
        proj.set("env:" + env['PIOENV'], field, value)
 | 
			
		||||
 | 
			
		||||
# All unused libs should be ignored so that if a library
 | 
			
		||||
# exists in .pio/lib_deps it will not break compilation.
 | 
			
		||||
def force_ignore_unused_libs():
 | 
			
		||||
	env_libs = get_all_env_libs()
 | 
			
		||||
	known_libs = get_all_known_libs()
 | 
			
		||||
	diff = (list(set(known_libs) - set(env_libs)))
 | 
			
		||||
	lib_ignore = env.GetProjectOption('lib_ignore') + diff
 | 
			
		||||
	if verbose:
 | 
			
		||||
		print("Ignore libraries:", lib_ignore)
 | 
			
		||||
	set_env_field('lib_ignore', lib_ignore)
 | 
			
		||||
    # All unused libs should be ignored so that if a library
 | 
			
		||||
    # exists in .pio/lib_deps it will not break compilation.
 | 
			
		||||
    def force_ignore_unused_libs():
 | 
			
		||||
        env_libs = get_all_env_libs()
 | 
			
		||||
        known_libs = get_all_known_libs()
 | 
			
		||||
        diff = (list(set(known_libs) - set(env_libs)))
 | 
			
		||||
        lib_ignore = env.GetProjectOption('lib_ignore') + diff
 | 
			
		||||
        blab("Ignore libraries: %s" % lib_ignore)
 | 
			
		||||
        set_env_field('lib_ignore', lib_ignore)
 | 
			
		||||
 | 
			
		||||
def apply_features_config():
 | 
			
		||||
	load_config()
 | 
			
		||||
	for feature in FEATURE_CONFIG:
 | 
			
		||||
		if not env.MarlinFeatureIsEnabled(feature):
 | 
			
		||||
			continue
 | 
			
		||||
    def apply_features_config():
 | 
			
		||||
        load_features()
 | 
			
		||||
        blab("========== Apply enabled features...")
 | 
			
		||||
        for feature in FEATURE_CONFIG:
 | 
			
		||||
            if not env.MarlinHas(feature):
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
		feat = FEATURE_CONFIG[feature]
 | 
			
		||||
            feat = FEATURE_CONFIG[feature]
 | 
			
		||||
 | 
			
		||||
		if 'lib_deps' in feat and len(feat['lib_deps']):
 | 
			
		||||
			blab("Adding lib_deps for %s... " % feature)
 | 
			
		||||
            if 'lib_deps' in feat and len(feat['lib_deps']):
 | 
			
		||||
                blab("========== Adding lib_deps for %s... " % feature, 2)
 | 
			
		||||
 | 
			
		||||
			# feat to add
 | 
			
		||||
			deps_to_add = {}
 | 
			
		||||
			for dep in feat['lib_deps']:
 | 
			
		||||
				name = parse_pkg_uri(dep)
 | 
			
		||||
				deps_to_add[name] = dep
 | 
			
		||||
                # feat to add
 | 
			
		||||
                deps_to_add = {}
 | 
			
		||||
                for dep in feat['lib_deps']:
 | 
			
		||||
                    deps_to_add[PackageSpec(dep).name] = dep
 | 
			
		||||
                    blab("==================== %s... " % dep, 2)
 | 
			
		||||
 | 
			
		||||
			# Does the env already have the dependency?
 | 
			
		||||
			deps = env.GetProjectOption('lib_deps')
 | 
			
		||||
			for dep in deps:
 | 
			
		||||
				name = parse_pkg_uri(dep)
 | 
			
		||||
				if name in deps_to_add:
 | 
			
		||||
					del deps_to_add[name]
 | 
			
		||||
                # Does the env already have the dependency?
 | 
			
		||||
                deps = env.GetProjectOption('lib_deps')
 | 
			
		||||
                for dep in deps:
 | 
			
		||||
                    name = PackageSpec(dep).name
 | 
			
		||||
                    if name in deps_to_add:
 | 
			
		||||
                        del deps_to_add[name]
 | 
			
		||||
 | 
			
		||||
			# Are there any libraries that should be ignored?
 | 
			
		||||
			lib_ignore = env.GetProjectOption('lib_ignore')
 | 
			
		||||
			for dep in deps:
 | 
			
		||||
				name = parse_pkg_uri(dep)
 | 
			
		||||
				if name in deps_to_add:
 | 
			
		||||
					del deps_to_add[name]
 | 
			
		||||
                # Are there any libraries that should be ignored?
 | 
			
		||||
                lib_ignore = env.GetProjectOption('lib_ignore')
 | 
			
		||||
                for dep in deps:
 | 
			
		||||
                    name = PackageSpec(dep).name
 | 
			
		||||
                    if name in deps_to_add:
 | 
			
		||||
                        del deps_to_add[name]
 | 
			
		||||
 | 
			
		||||
			# Is there anything left?
 | 
			
		||||
			if len(deps_to_add) > 0:
 | 
			
		||||
				# Only add the missing dependencies
 | 
			
		||||
				set_env_field('lib_deps', deps + list(deps_to_add.values()))
 | 
			
		||||
                # Is there anything left?
 | 
			
		||||
                if len(deps_to_add) > 0:
 | 
			
		||||
                    # Only add the missing dependencies
 | 
			
		||||
                    set_env_field('lib_deps', deps + list(deps_to_add.values()))
 | 
			
		||||
 | 
			
		||||
		if 'extra_scripts' in feat:
 | 
			
		||||
			blab("Running extra_scripts for %s... " % feature)
 | 
			
		||||
			env.SConscript(feat['extra_scripts'], exports="env")
 | 
			
		||||
            if 'build_flags' in feat:
 | 
			
		||||
                f = feat['build_flags']
 | 
			
		||||
                blab("========== Adding build_flags for %s: %s" % (feature, f), 2)
 | 
			
		||||
                new_flags = env.GetProjectOption('build_flags') + [ f ]
 | 
			
		||||
                env.Replace(BUILD_FLAGS=new_flags)
 | 
			
		||||
 | 
			
		||||
		if 'src_filter' in feat:
 | 
			
		||||
			blab("Adding src_filter for %s... " % feature)
 | 
			
		||||
			src_filter = ' '.join(env.GetProjectOption('src_filter'))
 | 
			
		||||
			# first we need to remove the references to the same folder
 | 
			
		||||
			my_srcs = re.findall( r'[+-](<.*?>)', feat['src_filter'])
 | 
			
		||||
			cur_srcs = re.findall( r'[+-](<.*?>)', src_filter)
 | 
			
		||||
			for d in my_srcs:
 | 
			
		||||
				if d in cur_srcs:
 | 
			
		||||
					src_filter = re.sub(r'[+-]' + d, '', src_filter)
 | 
			
		||||
            if 'extra_scripts' in feat:
 | 
			
		||||
                blab("Running extra_scripts for %s... " % feature, 2)
 | 
			
		||||
                env.SConscript(feat['extra_scripts'], exports="env")
 | 
			
		||||
 | 
			
		||||
			src_filter = feat['src_filter'] + ' ' + src_filter
 | 
			
		||||
			set_env_field('src_filter', [src_filter])
 | 
			
		||||
			env.Replace(SRC_FILTER=src_filter)
 | 
			
		||||
            if 'src_filter' in feat:
 | 
			
		||||
                blab("========== Adding build_src_filter for %s... " % feature, 2)
 | 
			
		||||
                src_filter = ' '.join(env.GetProjectOption('src_filter'))
 | 
			
		||||
                # first we need to remove the references to the same folder
 | 
			
		||||
                my_srcs = re.findall(r'[+-](<.*?>)', feat['src_filter'])
 | 
			
		||||
                cur_srcs = re.findall(r'[+-](<.*?>)', src_filter)
 | 
			
		||||
                for d in my_srcs:
 | 
			
		||||
                    if d in cur_srcs:
 | 
			
		||||
                        src_filter = re.sub(r'[+-]' + d, '', src_filter)
 | 
			
		||||
 | 
			
		||||
		if 'lib_ignore' in feat:
 | 
			
		||||
			blab("Adding lib_ignore for %s... " % feature)
 | 
			
		||||
			lib_ignore = env.GetProjectOption('lib_ignore') + [feat['lib_ignore']]
 | 
			
		||||
			set_env_field('lib_ignore', lib_ignore)
 | 
			
		||||
                src_filter = feat['src_filter'] + ' ' + src_filter
 | 
			
		||||
                set_env_field('build_src_filter', [src_filter])
 | 
			
		||||
                env.Replace(SRC_FILTER=src_filter)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Find a compiler, considering the OS
 | 
			
		||||
#
 | 
			
		||||
ENV_BUILD_PATH = os.path.join(env.Dictionary('PROJECT_BUILD_DIR'), env['PIOENV'])
 | 
			
		||||
GCC_PATH_CACHE = os.path.join(ENV_BUILD_PATH, ".gcc_path")
 | 
			
		||||
def search_compiler():
 | 
			
		||||
	try:
 | 
			
		||||
		filepath = env.GetProjectOption('custom_gcc')
 | 
			
		||||
		blab('Getting compiler from env')
 | 
			
		||||
		return filepath
 | 
			
		||||
	except:
 | 
			
		||||
		pass
 | 
			
		||||
            if 'lib_ignore' in feat:
 | 
			
		||||
                blab("========== Adding lib_ignore for %s... " % feature, 2)
 | 
			
		||||
                lib_ignore = env.GetProjectOption('lib_ignore') + [feat['lib_ignore']]
 | 
			
		||||
                set_env_field('lib_ignore', lib_ignore)
 | 
			
		||||
 | 
			
		||||
	if os.path.exists(GCC_PATH_CACHE):
 | 
			
		||||
		blab('Getting g++ path from cache')
 | 
			
		||||
		with open(GCC_PATH_CACHE, 'r') as f:
 | 
			
		||||
			return f.read()
 | 
			
		||||
    #
 | 
			
		||||
    # Use the compiler to get a list of all enabled features
 | 
			
		||||
    #
 | 
			
		||||
    def load_marlin_features():
 | 
			
		||||
        if 'MARLIN_FEATURES' in env:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
	# Find the current platform compiler by searching the $PATH
 | 
			
		||||
	# which will be in a platformio toolchain bin folder
 | 
			
		||||
	path_regex = re.escape(env['PROJECT_PACKAGES_DIR'])
 | 
			
		||||
	gcc = "g++"
 | 
			
		||||
	if env['PLATFORM'] == 'win32':
 | 
			
		||||
		path_separator = ';'
 | 
			
		||||
		path_regex += r'.*\\bin'
 | 
			
		||||
		gcc += ".exe"
 | 
			
		||||
	else:
 | 
			
		||||
		path_separator = ':'
 | 
			
		||||
		path_regex += r'/.+/bin'
 | 
			
		||||
        # Process defines
 | 
			
		||||
        from preprocessor import run_preprocessor
 | 
			
		||||
        define_list = run_preprocessor(env)
 | 
			
		||||
        marlin_features = {}
 | 
			
		||||
        for define in define_list:
 | 
			
		||||
            feature = define[8:].strip().decode().split(' ')
 | 
			
		||||
            feature, definition = feature[0], ' '.join(feature[1:])
 | 
			
		||||
            marlin_features[feature] = definition
 | 
			
		||||
        env['MARLIN_FEATURES'] = marlin_features
 | 
			
		||||
 | 
			
		||||
	# Search for the compiler
 | 
			
		||||
	for pathdir in env['ENV']['PATH'].split(path_separator):
 | 
			
		||||
		if not re.search(path_regex, pathdir, re.IGNORECASE):
 | 
			
		||||
			continue
 | 
			
		||||
		for filepath in os.listdir(pathdir):
 | 
			
		||||
			if not filepath.endswith(gcc):
 | 
			
		||||
				continue
 | 
			
		||||
    #
 | 
			
		||||
    # Return True if a matching feature is enabled
 | 
			
		||||
    #
 | 
			
		||||
    def MarlinHas(env, feature):
 | 
			
		||||
        load_marlin_features()
 | 
			
		||||
        r = re.compile('^' + feature + '$')
 | 
			
		||||
        found = list(filter(r.match, env['MARLIN_FEATURES']))
 | 
			
		||||
 | 
			
		||||
			# Cache the g++ path to no search always
 | 
			
		||||
			if os.path.exists(ENV_BUILD_PATH):
 | 
			
		||||
				blab('Caching g++ for current env')
 | 
			
		||||
				with open(GCC_PATH_CACHE, 'w+') as f:
 | 
			
		||||
					f.write(filepath)
 | 
			
		||||
        # Defines could still be 'false' or '0', so check
 | 
			
		||||
        some_on = False
 | 
			
		||||
        if len(found):
 | 
			
		||||
            for f in found:
 | 
			
		||||
                val = env['MARLIN_FEATURES'][f]
 | 
			
		||||
                if val in [ '', '1', 'true' ]:
 | 
			
		||||
                    some_on = True
 | 
			
		||||
                elif val in env['MARLIN_FEATURES']:
 | 
			
		||||
                    some_on = env.MarlinHas(val)
 | 
			
		||||
 | 
			
		||||
			return filepath
 | 
			
		||||
        return some_on
 | 
			
		||||
 | 
			
		||||
	filepath = env.get('CXX')
 | 
			
		||||
	blab("Couldn't find a compiler! Fallback to %s" % filepath)
 | 
			
		||||
	return filepath
 | 
			
		||||
    validate_pio()
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Use the compiler to get a list of all enabled features
 | 
			
		||||
#
 | 
			
		||||
def load_marlin_features():
 | 
			
		||||
	if 'MARLIN_FEATURES' in env:
 | 
			
		||||
		return
 | 
			
		||||
    try:
 | 
			
		||||
        verbose = int(env.GetProjectOption('custom_verbose'))
 | 
			
		||||
    except:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
	# Process defines
 | 
			
		||||
	build_flags = env.get('BUILD_FLAGS')
 | 
			
		||||
	build_flags = env.ParseFlagsExtended(build_flags)
 | 
			
		||||
    #
 | 
			
		||||
    # Add a method for other PIO scripts to query enabled features
 | 
			
		||||
    #
 | 
			
		||||
    env.AddMethod(MarlinHas)
 | 
			
		||||
 | 
			
		||||
	cxx = search_compiler()
 | 
			
		||||
	cmd = [cxx]
 | 
			
		||||
    #
 | 
			
		||||
    # Add dependencies for enabled Marlin features
 | 
			
		||||
    #
 | 
			
		||||
    apply_features_config()
 | 
			
		||||
    force_ignore_unused_libs()
 | 
			
		||||
 | 
			
		||||
	# Build flags from board.json
 | 
			
		||||
	#if 'BOARD' in env:
 | 
			
		||||
	#	cmd += [env.BoardConfig().get("build.extra_flags")]
 | 
			
		||||
	for s in build_flags['CPPDEFINES']:
 | 
			
		||||
		if isinstance(s, tuple):
 | 
			
		||||
			cmd += ['-D' + s[0] + '=' + str(s[1])]
 | 
			
		||||
		else:
 | 
			
		||||
			cmd += ['-D' + s]
 | 
			
		||||
    #print(env.Dump())
 | 
			
		||||
 | 
			
		||||
	cmd += ['-D__MARLIN_DEPS__ -w -dM -E -x c++ buildroot/share/PlatformIO/scripts/common-dependencies.h']
 | 
			
		||||
	cmd = ' '.join(cmd)
 | 
			
		||||
	blab(cmd)
 | 
			
		||||
	define_list = subprocess.check_output(cmd, shell=True).splitlines()
 | 
			
		||||
	marlin_features = {}
 | 
			
		||||
	for define in define_list:
 | 
			
		||||
		feature = define[8:].strip().decode().split(' ')
 | 
			
		||||
		feature, definition = feature[0], ' '.join(feature[1:])
 | 
			
		||||
		marlin_features[feature] = definition
 | 
			
		||||
	env['MARLIN_FEATURES'] = marlin_features
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Return True if a matching feature is enabled
 | 
			
		||||
#
 | 
			
		||||
def MarlinFeatureIsEnabled(env, feature):
 | 
			
		||||
	load_marlin_features()
 | 
			
		||||
	r = re.compile('^' + feature + '$')
 | 
			
		||||
	found = list(filter(r.match, env['MARLIN_FEATURES']))
 | 
			
		||||
 | 
			
		||||
	# Defines could still be 'false' or '0', so check
 | 
			
		||||
	some_on = False
 | 
			
		||||
	if len(found):
 | 
			
		||||
		for f in found:
 | 
			
		||||
			val = env['MARLIN_FEATURES'][f]
 | 
			
		||||
			if val in [ '', '1', 'true' ]:
 | 
			
		||||
				some_on = True
 | 
			
		||||
			elif val in env['MARLIN_FEATURES']:
 | 
			
		||||
				some_on = env.MarlinFeatureIsEnabled(val)
 | 
			
		||||
 | 
			
		||||
	return some_on
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Add a method for other PIO scripts to query enabled features
 | 
			
		||||
#
 | 
			
		||||
env.AddMethod(MarlinFeatureIsEnabled)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Add dependencies for enabled Marlin features
 | 
			
		||||
#
 | 
			
		||||
apply_features_config()
 | 
			
		||||
force_ignore_unused_libs()
 | 
			
		||||
    from signature import compute_build_signature
 | 
			
		||||
    compute_build_signature(env)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										239
									
								
								buildroot/share/PlatformIO/scripts/configuration.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								buildroot/share/PlatformIO/scripts/configuration.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,239 @@
 | 
			
		||||
#
 | 
			
		||||
# configuration.py
 | 
			
		||||
# Apply options from config.ini to the existing Configuration headers
 | 
			
		||||
#
 | 
			
		||||
import re, shutil, configparser
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
verbose = 0
 | 
			
		||||
def blab(str,level=1):
 | 
			
		||||
    if verbose >= level: print(f"[config] {str}")
 | 
			
		||||
 | 
			
		||||
def config_path(cpath):
 | 
			
		||||
    return Path("Marlin", cpath, encoding='utf-8')
 | 
			
		||||
 | 
			
		||||
# Apply a single name = on/off ; name = value ; etc.
 | 
			
		||||
# TODO: Limit to the given (optional) configuration
 | 
			
		||||
def apply_opt(name, val, conf=None):
 | 
			
		||||
    if name == "lcd": name, val = val, "on"
 | 
			
		||||
 | 
			
		||||
    # Create a regex to match the option and capture parts of the line
 | 
			
		||||
    regex = re.compile(rf'^(\s*)(//\s*)?(#define\s+)({name}\b)(\s*)(.*?)(\s*)(//.*)?$', re.IGNORECASE)
 | 
			
		||||
 | 
			
		||||
    # Find and enable and/or update all matches
 | 
			
		||||
    for file in ("Configuration.h", "Configuration_adv.h"):
 | 
			
		||||
        fullpath = config_path(file)
 | 
			
		||||
        lines = fullpath.read_text(encoding='utf-8').split('\n')
 | 
			
		||||
        found = False
 | 
			
		||||
        for i in range(len(lines)):
 | 
			
		||||
            line = lines[i]
 | 
			
		||||
            match = regex.match(line)
 | 
			
		||||
            if match and match[4].upper() == name.upper():
 | 
			
		||||
                found = True
 | 
			
		||||
                # For boolean options un/comment the define
 | 
			
		||||
                if val in ("on", "", None):
 | 
			
		||||
                    newline = re.sub(r'^(\s*)//+\s*(#define)(\s{1,3})?(\s*)', r'\1\2 \4', line)
 | 
			
		||||
                elif val == "off":
 | 
			
		||||
                    newline = re.sub(r'^(\s*)(#define)(\s{1,3})?(\s*)', r'\1//\2 \4', line)
 | 
			
		||||
                else:
 | 
			
		||||
                    # For options with values, enable and set the value
 | 
			
		||||
                    newline = match[1] + match[3] + match[4] + match[5] + val
 | 
			
		||||
                    if match[8]:
 | 
			
		||||
                        sp = match[7] if match[7] else ' '
 | 
			
		||||
                        newline += sp + match[8]
 | 
			
		||||
                lines[i] = newline
 | 
			
		||||
                blab(f"Set {name} to {val}")
 | 
			
		||||
 | 
			
		||||
        # If the option was found, write the modified lines
 | 
			
		||||
        if found:
 | 
			
		||||
            fullpath.write_text('\n'.join(lines), encoding='utf-8')
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
    # If the option didn't appear in either config file, add it
 | 
			
		||||
    if not found:
 | 
			
		||||
        # OFF options are added as disabled items so they appear
 | 
			
		||||
        # in config dumps. Useful for custom settings.
 | 
			
		||||
        prefix = ""
 | 
			
		||||
        if val == "off":
 | 
			
		||||
            prefix, val = "//", ""  # Item doesn't appear in config dump
 | 
			
		||||
            #val = "false"          # Item appears in config dump
 | 
			
		||||
 | 
			
		||||
        # Uppercase the option unless already mixed/uppercase
 | 
			
		||||
        added = name.upper() if name.islower() else name
 | 
			
		||||
 | 
			
		||||
        # Add the provided value after the name
 | 
			
		||||
        if val != "on" and val != "" and val is not None:
 | 
			
		||||
            added += " " + val
 | 
			
		||||
 | 
			
		||||
        # Prepend the new option after the first set of #define lines
 | 
			
		||||
        fullpath = config_path("Configuration.h")
 | 
			
		||||
        with fullpath.open(encoding='utf-8') as f:
 | 
			
		||||
            lines = f.readlines()
 | 
			
		||||
            linenum = 0
 | 
			
		||||
            gotdef = False
 | 
			
		||||
            for line in lines:
 | 
			
		||||
                isdef = line.startswith("#define")
 | 
			
		||||
                if not gotdef:
 | 
			
		||||
                    gotdef = isdef
 | 
			
		||||
                elif not isdef:
 | 
			
		||||
                    break
 | 
			
		||||
                linenum += 1
 | 
			
		||||
            lines.insert(linenum, f"{prefix}#define {added:30} // Added by config.ini\n")
 | 
			
		||||
            fullpath.write_text(''.join(lines), encoding='utf-8')
 | 
			
		||||
 | 
			
		||||
# Fetch configuration files from GitHub given the path.
 | 
			
		||||
# Return True if any files were fetched.
 | 
			
		||||
def fetch_example(url):
 | 
			
		||||
    if url.endswith("/"): url = url[:-1]
 | 
			
		||||
    if url.startswith('http'):
 | 
			
		||||
        url = url.replace("%", "%25").replace(" ", "%20")
 | 
			
		||||
    else:
 | 
			
		||||
        brch = "bugfix-2.1.x"
 | 
			
		||||
        if '@' in path: path, brch = map(str.strip, path.split('@'))
 | 
			
		||||
        url = f"https://raw.githubusercontent.com/MarlinFirmware/Configurations/{brch}/config/{url}"
 | 
			
		||||
 | 
			
		||||
    # Find a suitable fetch command
 | 
			
		||||
    if shutil.which("curl") is not None:
 | 
			
		||||
        fetch = "curl -L -s -S -f -o"
 | 
			
		||||
    elif shutil.which("wget") is not None:
 | 
			
		||||
        fetch = "wget -q -O"
 | 
			
		||||
    else:
 | 
			
		||||
        blab("Couldn't find curl or wget", -1)
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    import os
 | 
			
		||||
 | 
			
		||||
    # Reset configurations to default
 | 
			
		||||
    os.system("git reset --hard HEAD")
 | 
			
		||||
 | 
			
		||||
    # Try to fetch the remote files
 | 
			
		||||
    gotfile = False
 | 
			
		||||
    for fn in ("Configuration.h", "Configuration_adv.h", "_Bootscreen.h", "_Statusscreen.h"):
 | 
			
		||||
        if os.system(f"{fetch} wgot {url}/{fn} >/dev/null 2>&1") == 0:
 | 
			
		||||
            shutil.move('wgot', config_path(fn))
 | 
			
		||||
            gotfile = True
 | 
			
		||||
 | 
			
		||||
    if Path('wgot').exists(): shutil.rmtree('wgot')
 | 
			
		||||
 | 
			
		||||
    return gotfile
 | 
			
		||||
 | 
			
		||||
def section_items(cp, sectkey):
 | 
			
		||||
    return cp.items(sectkey) if sectkey in cp.sections() else []
 | 
			
		||||
 | 
			
		||||
# Apply all items from a config section
 | 
			
		||||
def apply_ini_by_name(cp, sect):
 | 
			
		||||
    iniok = True
 | 
			
		||||
    if sect in ('config:base', 'config:root'):
 | 
			
		||||
        iniok = False
 | 
			
		||||
        items = section_items(cp, 'config:base') + section_items(cp, 'config:root')
 | 
			
		||||
    else:
 | 
			
		||||
        items = section_items(cp, sect)
 | 
			
		||||
 | 
			
		||||
    for item in items:
 | 
			
		||||
        if iniok or not item[0].startswith('ini_'):
 | 
			
		||||
            apply_opt(item[0], item[1])
 | 
			
		||||
 | 
			
		||||
# Apply all config sections from a parsed file
 | 
			
		||||
def apply_all_sections(cp):
 | 
			
		||||
    for sect in cp.sections():
 | 
			
		||||
        if sect.startswith('config:'):
 | 
			
		||||
            apply_ini_by_name(cp, sect)
 | 
			
		||||
 | 
			
		||||
# Apply certain config sections from a parsed file
 | 
			
		||||
def apply_sections(cp, ckey='all'):
 | 
			
		||||
    blab(f"Apply section key: {ckey}")
 | 
			
		||||
    if ckey == 'all':
 | 
			
		||||
        apply_all_sections(cp)
 | 
			
		||||
    else:
 | 
			
		||||
        # Apply the base/root config.ini settings after external files are done
 | 
			
		||||
        if ckey in ('base', 'root'):
 | 
			
		||||
            apply_ini_by_name(cp, 'config:base')
 | 
			
		||||
 | 
			
		||||
        # Apply historically 'Configuration.h' settings everywhere
 | 
			
		||||
        if ckey == 'basic':
 | 
			
		||||
            apply_ini_by_name(cp, 'config:basic')
 | 
			
		||||
 | 
			
		||||
        # Apply historically Configuration_adv.h settings everywhere
 | 
			
		||||
        # (Some of which rely on defines in 'Conditionals_LCD.h')
 | 
			
		||||
        elif ckey in ('adv', 'advanced'):
 | 
			
		||||
            apply_ini_by_name(cp, 'config:advanced')
 | 
			
		||||
 | 
			
		||||
        # Apply a specific config:<name> section directly
 | 
			
		||||
        elif ckey.startswith('config:'):
 | 
			
		||||
            apply_ini_by_name(cp, ckey)
 | 
			
		||||
 | 
			
		||||
# Apply settings from a top level config.ini
 | 
			
		||||
def apply_config_ini(cp):
 | 
			
		||||
    blab("=" * 20 + " Gather 'config.ini' entries...")
 | 
			
		||||
 | 
			
		||||
    # Pre-scan for ini_use_config to get config_keys
 | 
			
		||||
    base_items = section_items(cp, 'config:base') + section_items(cp, 'config:root')
 | 
			
		||||
    config_keys = ['base']
 | 
			
		||||
    for ikey, ival in base_items:
 | 
			
		||||
        if ikey == 'ini_use_config':
 | 
			
		||||
            config_keys = map(str.strip, ival.split(','))
 | 
			
		||||
 | 
			
		||||
    # For each ini_use_config item perform an action
 | 
			
		||||
    for ckey in config_keys:
 | 
			
		||||
        addbase = False
 | 
			
		||||
 | 
			
		||||
        # For a key ending in .ini load and parse another .ini file
 | 
			
		||||
        if ckey.endswith('.ini'):
 | 
			
		||||
            sect = 'base'
 | 
			
		||||
            if '@' in ckey: sect, ckey = ckey.split('@')
 | 
			
		||||
            other_ini = configparser.ConfigParser()
 | 
			
		||||
            other_ini.read(config_path(ckey))
 | 
			
		||||
            apply_sections(other_ini, sect)
 | 
			
		||||
 | 
			
		||||
        # (Allow 'example/' as a shortcut for 'examples/')
 | 
			
		||||
        elif ckey.startswith('example/'):
 | 
			
		||||
            ckey = 'examples' + ckey[7:]
 | 
			
		||||
 | 
			
		||||
        # For 'examples/<path>' fetch an example set from GitHub.
 | 
			
		||||
        # For https?:// do a direct fetch of the URL.
 | 
			
		||||
        elif ckey.startswith('examples/') or ckey.startswith('http'):
 | 
			
		||||
            fetch_example(ckey)
 | 
			
		||||
            ckey = 'base'
 | 
			
		||||
 | 
			
		||||
        elif ckey == 'all':
 | 
			
		||||
            apply_sections(cp)
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            # Apply keyed sections after external files are done
 | 
			
		||||
            apply_sections(cp, 'config:' + ckey)
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    #
 | 
			
		||||
    # From command line use the given file name
 | 
			
		||||
    #
 | 
			
		||||
    import sys
 | 
			
		||||
    args = sys.argv[1:]
 | 
			
		||||
    if len(args) > 0:
 | 
			
		||||
        if args[0].endswith('.ini'):
 | 
			
		||||
            ini_file = args[0]
 | 
			
		||||
        else:
 | 
			
		||||
            print("Usage: %s <.ini file>" % sys.argv[0])
 | 
			
		||||
    else:
 | 
			
		||||
        ini_file = config_path('config.ini')
 | 
			
		||||
 | 
			
		||||
    if ini_file:
 | 
			
		||||
        user_ini = configparser.ConfigParser()
 | 
			
		||||
        user_ini.read(ini_file)
 | 
			
		||||
        apply_config_ini(user_ini)
 | 
			
		||||
 | 
			
		||||
else:
 | 
			
		||||
    #
 | 
			
		||||
    # From within PlatformIO use the loaded INI file
 | 
			
		||||
    #
 | 
			
		||||
    import pioutil
 | 
			
		||||
    if pioutil.is_pio_build():
 | 
			
		||||
 | 
			
		||||
        Import("env")
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            verbose = int(env.GetProjectOption('custom_verbose'))
 | 
			
		||||
        except:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        from platformio.project.config import ProjectConfig
 | 
			
		||||
        apply_config_ini(ProjectConfig())
 | 
			
		||||
@@ -1,58 +0,0 @@
 | 
			
		||||
import os,shutil
 | 
			
		||||
from SCons.Script import DefaultEnvironment
 | 
			
		||||
from platformio import util
 | 
			
		||||
try:
 | 
			
		||||
    # PIO < 4.4
 | 
			
		||||
    from platformio.managers.package import PackageManager
 | 
			
		||||
except ImportError:
 | 
			
		||||
    # PIO >= 4.4
 | 
			
		||||
    from platformio.package.meta import PackageSpec as PackageManager
 | 
			
		||||
 | 
			
		||||
def parse_pkg_uri(spec):
 | 
			
		||||
    if PackageManager.__name__ == 'PackageSpec':
 | 
			
		||||
        return PackageManager(spec).name
 | 
			
		||||
    else:
 | 
			
		||||
        name, _, _ = PackageManager.parse_pkg_uri(spec)
 | 
			
		||||
        return name
 | 
			
		||||
 | 
			
		||||
def copytree(src, dst, symlinks=False, ignore=None):
 | 
			
		||||
    for item in os.listdir(src):
 | 
			
		||||
        s = os.path.join(src, item)
 | 
			
		||||
        d = os.path.join(dst, item)
 | 
			
		||||
        if os.path.isdir(s):
 | 
			
		||||
            shutil.copytree(s, d, symlinks, ignore)
 | 
			
		||||
        else:
 | 
			
		||||
            shutil.copy2(s, d)
 | 
			
		||||
 | 
			
		||||
env = DefaultEnvironment()
 | 
			
		||||
platform = env.PioPlatform()
 | 
			
		||||
board = env.BoardConfig()
 | 
			
		||||
variant = board.get("build.variant")
 | 
			
		||||
 | 
			
		||||
platform_packages = env.GetProjectOption('platform_packages')
 | 
			
		||||
# if there's no framework defined, take it from the class name of platform
 | 
			
		||||
framewords = {
 | 
			
		||||
    "Ststm32Platform": "framework-arduinoststm32",
 | 
			
		||||
    "AtmelavrPlatform": "framework-arduino-avr"
 | 
			
		||||
}
 | 
			
		||||
if len(platform_packages) == 0:
 | 
			
		||||
    platform_name = framewords[platform.__class__.__name__]
 | 
			
		||||
else:
 | 
			
		||||
    platform_name = parse_pkg_uri(platform_packages[0])
 | 
			
		||||
 | 
			
		||||
FRAMEWORK_DIR = platform.get_package_dir(platform_name)
 | 
			
		||||
assert os.path.isdir(FRAMEWORK_DIR)
 | 
			
		||||
assert os.path.isdir("buildroot/share/PlatformIO/variants")
 | 
			
		||||
 | 
			
		||||
variant_dir = os.path.join(FRAMEWORK_DIR, "variants", variant)
 | 
			
		||||
 | 
			
		||||
source_dir = os.path.join("buildroot/share/PlatformIO/variants", variant)
 | 
			
		||||
assert os.path.isdir(source_dir)
 | 
			
		||||
 | 
			
		||||
if os.path.isdir(variant_dir):
 | 
			
		||||
    shutil.rmtree(variant_dir)
 | 
			
		||||
 | 
			
		||||
if not os.path.isdir(variant_dir):
 | 
			
		||||
    os.mkdir(variant_dir)
 | 
			
		||||
 | 
			
		||||
copytree(source_dir, variant_dir)
 | 
			
		||||
@@ -1,17 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08007000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/creality.ld")
 | 
			
		||||
 | 
			
		||||
for i, flag in enumerate(env['LINKFLAGS']):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env['LINKFLAGS'][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env['LINKFLAGS'][i + 1] = custom_ld_script
 | 
			
		||||
							
								
								
									
										18
									
								
								buildroot/share/PlatformIO/scripts/custom_board.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								buildroot/share/PlatformIO/scripts/custom_board.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
#
 | 
			
		||||
# custom_board.py
 | 
			
		||||
#
 | 
			
		||||
# - For build.address replace VECT_TAB_ADDR to relocate the firmware
 | 
			
		||||
# - For build.ldscript use one of the linker scripts in buildroot/share/PlatformIO/ldscripts
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    import marlin
 | 
			
		||||
    board = marlin.env.BoardConfig()
 | 
			
		||||
 | 
			
		||||
    address = board.get("build.address", "")
 | 
			
		||||
    if address:
 | 
			
		||||
        marlin.relocate_firmware(address)
 | 
			
		||||
 | 
			
		||||
    ldscript = board.get("build.ldscript", "")
 | 
			
		||||
    if ldscript:
 | 
			
		||||
        marlin.custom_ld_script(ldscript)
 | 
			
		||||
@@ -1,46 +1,53 @@
 | 
			
		||||
Import("env")
 | 
			
		||||
import os
 | 
			
		||||
import requests
 | 
			
		||||
import zipfile
 | 
			
		||||
import tempfile
 | 
			
		||||
import shutil
 | 
			
		||||
#
 | 
			
		||||
# download_mks_assets.py
 | 
			
		||||
# Added by HAS_TFT_LVGL_UI to download assets from Makerbase repo
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    Import("env")
 | 
			
		||||
    import requests,zipfile,tempfile,shutil
 | 
			
		||||
    from pathlib import Path
 | 
			
		||||
 | 
			
		||||
url = "https://github.com/makerbase-mks/Mks-Robin-Nano-Marlin2.0-Firmware/archive/master.zip"
 | 
			
		||||
zip_path = os.path.join(env.Dictionary("PROJECT_LIBDEPS_DIR"), "mks-assets.zip")
 | 
			
		||||
assets_path = os.path.join(env.Dictionary("PROJECT_BUILD_DIR"), env.Dictionary("PIOENV"), "assets")
 | 
			
		||||
    url = "https://github.com/makerbase-mks/Mks-Robin-Nano-Marlin2.0-Firmware/archive/0263cdaccf.zip"
 | 
			
		||||
    deps_path = Path(env.Dictionary("PROJECT_LIBDEPS_DIR"))
 | 
			
		||||
    zip_path = deps_path / "mks-assets.zip"
 | 
			
		||||
    assets_path = Path(env.Dictionary("PROJECT_BUILD_DIR"), env.Dictionary("PIOENV"), "assets")
 | 
			
		||||
 | 
			
		||||
def download_mks_assets():
 | 
			
		||||
	print("Downloading MKS Assets")
 | 
			
		||||
	r = requests.get(url, stream=True)
 | 
			
		||||
	# the user may have a very clean workspace,
 | 
			
		||||
	# so create the PROJECT_LIBDEPS_DIR directory if not exits
 | 
			
		||||
	if os.path.exists(env.Dictionary("PROJECT_LIBDEPS_DIR")) == False:
 | 
			
		||||
		os.mkdir(env.Dictionary("PROJECT_LIBDEPS_DIR"))
 | 
			
		||||
	with open(zip_path, 'wb') as fd:
 | 
			
		||||
		for chunk in r.iter_content(chunk_size=128):
 | 
			
		||||
			fd.write(chunk)
 | 
			
		||||
    def download_mks_assets():
 | 
			
		||||
        print("Downloading MKS Assets")
 | 
			
		||||
        r = requests.get(url, stream=True)
 | 
			
		||||
        # the user may have a very clean workspace,
 | 
			
		||||
        # so create the PROJECT_LIBDEPS_DIR directory if not exits
 | 
			
		||||
        if not deps_path.exists():
 | 
			
		||||
            deps_path.mkdir()
 | 
			
		||||
        with zip_path.open('wb') as fd:
 | 
			
		||||
            for chunk in r.iter_content(chunk_size=128):
 | 
			
		||||
                fd.write(chunk)
 | 
			
		||||
 | 
			
		||||
def copy_mks_assets():
 | 
			
		||||
	print("Copying MKS Assets")
 | 
			
		||||
	output_path = tempfile.mkdtemp()
 | 
			
		||||
	zip_obj = zipfile.ZipFile(zip_path, 'r')
 | 
			
		||||
	zip_obj.extractall(output_path)
 | 
			
		||||
	zip_obj.close()
 | 
			
		||||
	if os.path.exists(assets_path) == True and os.path.isdir(assets_path) == False:
 | 
			
		||||
		os.unlink(assets_path)
 | 
			
		||||
	if os.path.exists(assets_path) == False:
 | 
			
		||||
		os.mkdir(assets_path)
 | 
			
		||||
	base_path = ''
 | 
			
		||||
	for filename in os.listdir(output_path):
 | 
			
		||||
		base_path = filename
 | 
			
		||||
	for filename in os.listdir(os.path.join(output_path, base_path, 'Firmware', 'mks_font')):
 | 
			
		||||
		shutil.copy(os.path.join(output_path, base_path, 'Firmware', 'mks_font', filename), assets_path)
 | 
			
		||||
	for filename in os.listdir(os.path.join(output_path, base_path, 'Firmware', 'mks_pic')):
 | 
			
		||||
		shutil.copy(os.path.join(output_path, base_path, 'Firmware', 'mks_pic', filename), assets_path)
 | 
			
		||||
	shutil.rmtree(output_path, ignore_errors=True)
 | 
			
		||||
    def copy_mks_assets():
 | 
			
		||||
        print("Copying MKS Assets")
 | 
			
		||||
        output_path = Path(tempfile.mkdtemp())
 | 
			
		||||
        zip_obj = zipfile.ZipFile(zip_path, 'r')
 | 
			
		||||
        zip_obj.extractall(output_path)
 | 
			
		||||
        zip_obj.close()
 | 
			
		||||
        if assets_path.exists() and not assets_path.is_dir():
 | 
			
		||||
            assets_path.unlink()
 | 
			
		||||
        if not assets_path.exists():
 | 
			
		||||
            assets_path.mkdir()
 | 
			
		||||
        base_path = ''
 | 
			
		||||
        for filename in output_path.iterdir():
 | 
			
		||||
            base_path = filename
 | 
			
		||||
        fw_path = (output_path / base_path / 'Firmware')
 | 
			
		||||
        font_path = fw_path / 'mks_font'
 | 
			
		||||
        for filename in font_path.iterdir():
 | 
			
		||||
            shutil.copy(font_path / filename, assets_path)
 | 
			
		||||
        pic_path = fw_path / 'mks_pic'
 | 
			
		||||
        for filename in pic_path.iterdir():
 | 
			
		||||
            shutil.copy(pic_path / filename, assets_path)
 | 
			
		||||
        shutil.rmtree(output_path, ignore_errors=True)
 | 
			
		||||
 | 
			
		||||
if os.path.exists(zip_path) == False:
 | 
			
		||||
	download_mks_assets()
 | 
			
		||||
    if not zip_path.exists():
 | 
			
		||||
        download_mks_assets()
 | 
			
		||||
 | 
			
		||||
if os.path.exists(assets_path) == False:
 | 
			
		||||
	copy_mks_assets()
 | 
			
		||||
    if not assets_path.exists():
 | 
			
		||||
        copy_mks_assets()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										104
									
								
								buildroot/share/PlatformIO/scripts/exc.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								buildroot/share/PlatformIO/scripts/exc.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
			
		||||
/* *****************************************************************************
 | 
			
		||||
 * The MIT License
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2010 Perry Hung.
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 * ****************************************************************************/
 | 
			
		||||
 | 
			
		||||
# On an exception, push a fake stack thread mode stack frame and redirect
 | 
			
		||||
# thread execution to a thread mode error handler
 | 
			
		||||
 | 
			
		||||
# From RM008:
 | 
			
		||||
# The SP is decremented by eight words by the completion of the stack push.
 | 
			
		||||
# Figure 5-1 shows the contents of the stack after an exception pre-empts the
 | 
			
		||||
# current program flow.
 | 
			
		||||
#
 | 
			
		||||
# Old SP--> <previous>
 | 
			
		||||
#           xPSR
 | 
			
		||||
#           PC
 | 
			
		||||
#           LR
 | 
			
		||||
#           r12
 | 
			
		||||
#           r3
 | 
			
		||||
#           r2
 | 
			
		||||
#           r1
 | 
			
		||||
#    SP-->  r0
 | 
			
		||||
 | 
			
		||||
.text
 | 
			
		||||
.globl __exc_nmi
 | 
			
		||||
.weak  __exc_nmi
 | 
			
		||||
.globl __exc_hardfault
 | 
			
		||||
.weak  __exc_hardfault
 | 
			
		||||
.globl __exc_memmanage
 | 
			
		||||
.weak  __exc_memmanage
 | 
			
		||||
.globl __exc_busfault
 | 
			
		||||
.weak  __exc_busfault
 | 
			
		||||
.globl __exc_usagefault
 | 
			
		||||
.weak  __exc_usagefault
 | 
			
		||||
 | 
			
		||||
.code 16
 | 
			
		||||
.thumb_func
 | 
			
		||||
__exc_nmi:
 | 
			
		||||
    mov r0, #1
 | 
			
		||||
    b __default_exc
 | 
			
		||||
 | 
			
		||||
.thumb_func
 | 
			
		||||
__exc_hardfault:
 | 
			
		||||
    mov r0, #2
 | 
			
		||||
    b __default_exc
 | 
			
		||||
 | 
			
		||||
.thumb_func
 | 
			
		||||
__exc_memmanage:
 | 
			
		||||
    mov r0, #3
 | 
			
		||||
    b __default_exc
 | 
			
		||||
 | 
			
		||||
.thumb_func
 | 
			
		||||
__exc_busfault:
 | 
			
		||||
    mov r0, #4
 | 
			
		||||
    b __default_exc
 | 
			
		||||
 | 
			
		||||
.thumb_func
 | 
			
		||||
__exc_usagefault:
 | 
			
		||||
    mov r0, #5
 | 
			
		||||
    b __default_exc
 | 
			
		||||
 | 
			
		||||
.thumb_func
 | 
			
		||||
__default_exc:
 | 
			
		||||
    ldr r2, NVIC_CCR            @ Enable returning to thread mode even if there are
 | 
			
		||||
    mov r1 ,#1                  @ pending exceptions. See flag NONEBASETHRDENA.
 | 
			
		||||
    str r1, [r2]
 | 
			
		||||
    cpsid i                     @ Disable global interrupts
 | 
			
		||||
    ldr r2, SYSTICK_CSR         @ Disable systick handler
 | 
			
		||||
    mov r1, #0
 | 
			
		||||
    str r1, [r2]
 | 
			
		||||
    ldr r1, CPSR_MASK           @ Set default CPSR
 | 
			
		||||
    push {r1}
 | 
			
		||||
    ldr r1, TARGET_PC           @ Set target pc
 | 
			
		||||
    push {r1}
 | 
			
		||||
    sub sp, sp, #24             @ Don't care
 | 
			
		||||
    ldr r1, EXC_RETURN          @ Return to thread mode
 | 
			
		||||
    mov lr, r1
 | 
			
		||||
    bx lr                       @ Exception exit
 | 
			
		||||
 | 
			
		||||
.align 4
 | 
			
		||||
CPSR_MASK:     .word 0x61000000
 | 
			
		||||
EXC_RETURN:    .word 0xFFFFFFF9
 | 
			
		||||
TARGET_PC:     .word __error
 | 
			
		||||
NVIC_CCR:      .word 0xE000ED14    @ NVIC configuration control register
 | 
			
		||||
SYSTICK_CSR:   .word 0xE000E010    @ Systick control register
 | 
			
		||||
							
								
								
									
										35
									
								
								buildroot/share/PlatformIO/scripts/fix_framework_weakness.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								buildroot/share/PlatformIO/scripts/fix_framework_weakness.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
#
 | 
			
		||||
# fix_framework_weakness.py
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
 | 
			
		||||
    import shutil
 | 
			
		||||
    from os.path import join, isfile
 | 
			
		||||
    from pprint import pprint
 | 
			
		||||
 | 
			
		||||
    Import("env")
 | 
			
		||||
 | 
			
		||||
    if env.MarlinHas("POSTMORTEM_DEBUGGING"):
 | 
			
		||||
        FRAMEWORK_DIR = env.PioPlatform().get_package_dir("framework-arduinoststm32-maple")
 | 
			
		||||
        patchflag_path = join(FRAMEWORK_DIR, ".exc-patching-done")
 | 
			
		||||
 | 
			
		||||
        # patch file only if we didn't do it before
 | 
			
		||||
        if not isfile(patchflag_path):
 | 
			
		||||
            print("Patching libmaple exception handlers")
 | 
			
		||||
            original_file = join(FRAMEWORK_DIR, "STM32F1", "cores", "maple", "libmaple", "exc.S")
 | 
			
		||||
            backup_file = join(FRAMEWORK_DIR, "STM32F1", "cores", "maple", "libmaple", "exc.S.bak")
 | 
			
		||||
            src_file = join("buildroot", "share", "PlatformIO", "scripts", "exc.S")
 | 
			
		||||
 | 
			
		||||
            assert isfile(original_file) and isfile(src_file)
 | 
			
		||||
            shutil.copyfile(original_file, backup_file)
 | 
			
		||||
            shutil.copyfile(src_file, original_file);
 | 
			
		||||
 | 
			
		||||
            def _touch(path):
 | 
			
		||||
                with open(path, "w") as fp:
 | 
			
		||||
                    fp.write("")
 | 
			
		||||
 | 
			
		||||
            env.Execute(lambda *args, **kwargs: _touch(patchflag_path))
 | 
			
		||||
            print("Done patching exception handler")
 | 
			
		||||
 | 
			
		||||
        print("Libmaple modified and ready for post mortem debugging")
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08005000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08005000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/fly_mini.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
@@ -1,27 +1,58 @@
 | 
			
		||||
import os,shutil
 | 
			
		||||
from SCons.Script import DefaultEnvironment
 | 
			
		||||
from platformio import util
 | 
			
		||||
#
 | 
			
		||||
# generic_create_variant.py
 | 
			
		||||
#
 | 
			
		||||
# Copy one of the variants from buildroot/platformio/variants into
 | 
			
		||||
# the appropriate framework variants folder, so that its contents
 | 
			
		||||
# will be picked up by PlatformIO just like any other variant.
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    import shutil,marlin
 | 
			
		||||
    from pathlib import Path
 | 
			
		||||
 | 
			
		||||
env = DefaultEnvironment()
 | 
			
		||||
platform = env.PioPlatform()
 | 
			
		||||
board = env.BoardConfig()
 | 
			
		||||
    #
 | 
			
		||||
    # Get the platform name from the 'platform_packages' option,
 | 
			
		||||
    # or look it up by the platform.class.name.
 | 
			
		||||
    #
 | 
			
		||||
    env = marlin.env
 | 
			
		||||
    platform = env.PioPlatform()
 | 
			
		||||
 | 
			
		||||
FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoststm32")
 | 
			
		||||
assert os.path.isdir(FRAMEWORK_DIR)
 | 
			
		||||
assert os.path.isdir("buildroot/share/PlatformIO/variants")
 | 
			
		||||
    from platformio.package.meta import PackageSpec
 | 
			
		||||
    platform_packages = env.GetProjectOption('platform_packages')
 | 
			
		||||
 | 
			
		||||
mcu_type = board.get("build.mcu")[:-2]
 | 
			
		||||
variant = board.get("build.variant")
 | 
			
		||||
series = mcu_type[:7].upper() + "xx"
 | 
			
		||||
variant_dir = os.path.join(FRAMEWORK_DIR, "variants", variant)
 | 
			
		||||
    # Remove all tool items from platform_packages
 | 
			
		||||
    platform_packages = [x for x in platform_packages if not x.startswith("platformio/tool-")]
 | 
			
		||||
 | 
			
		||||
source_dir = os.path.join("buildroot/share/PlatformIO/variants", variant)
 | 
			
		||||
assert os.path.isdir(source_dir)
 | 
			
		||||
    if len(platform_packages) == 0:
 | 
			
		||||
        framewords = {
 | 
			
		||||
            "Ststm32Platform": "framework-arduinoststm32",
 | 
			
		||||
            "AtmelavrPlatform": "framework-arduino-avr"
 | 
			
		||||
        }
 | 
			
		||||
        platform_name = framewords[platform.__class__.__name__]
 | 
			
		||||
    else:
 | 
			
		||||
        platform_name = PackageSpec(platform_packages[0]).name
 | 
			
		||||
 | 
			
		||||
if not os.path.isdir(variant_dir):
 | 
			
		||||
    os.mkdir(variant_dir)
 | 
			
		||||
    if platform_name in [ "usb-host-msc", "usb-host-msc-cdc-msc", "usb-host-msc-cdc-msc-2", "usb-host-msc-cdc-msc-3", "tool-stm32duino", "biqu-bx-workaround", "main" ]:
 | 
			
		||||
        platform_name = "framework-arduinoststm32"
 | 
			
		||||
 | 
			
		||||
for file_name in os.listdir(source_dir):
 | 
			
		||||
    full_file_name = os.path.join(source_dir, file_name)
 | 
			
		||||
    if os.path.isfile(full_file_name):
 | 
			
		||||
        shutil.copy(full_file_name, variant_dir)
 | 
			
		||||
    FRAMEWORK_DIR = Path(platform.get_package_dir(platform_name))
 | 
			
		||||
    assert FRAMEWORK_DIR.is_dir()
 | 
			
		||||
 | 
			
		||||
    board = env.BoardConfig()
 | 
			
		||||
 | 
			
		||||
    #mcu_type = board.get("build.mcu")[:-2]
 | 
			
		||||
    variant = board.get("build.variant")
 | 
			
		||||
    #series = mcu_type[:7].upper() + "xx"
 | 
			
		||||
 | 
			
		||||
    # Prepare a new empty folder at the destination
 | 
			
		||||
    variant_dir = FRAMEWORK_DIR / "variants" / variant
 | 
			
		||||
    if variant_dir.is_dir():
 | 
			
		||||
        shutil.rmtree(variant_dir)
 | 
			
		||||
    if not variant_dir.is_dir():
 | 
			
		||||
        variant_dir.mkdir()
 | 
			
		||||
 | 
			
		||||
    # Source dir is a local variant sub-folder
 | 
			
		||||
    source_dir = Path("buildroot/share/PlatformIO/variants", variant)
 | 
			
		||||
    assert source_dir.is_dir()
 | 
			
		||||
 | 
			
		||||
    marlin.copytree(source_dir, variant_dir)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,48 +1,35 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
#
 | 
			
		||||
# jgaurora_a5s_a1_with_bootloader.py
 | 
			
		||||
# Customizations for env:jgaurora_a5s_a1
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x0800A000
 | 
			
		||||
env['CPPDEFINES'].remove(("VECT_TAB_ADDR", "0x8000000"))
 | 
			
		||||
#alternatively, for STSTM <=5.1.0 use line below
 | 
			
		||||
#env['CPPDEFINES'].remove(("VECT_TAB_ADDR", 134217728))
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x0800A000"))
 | 
			
		||||
    # Append ${PROGNAME}.bin firmware after bootloader and save it as 'jgaurora_firmware.bin'
 | 
			
		||||
    def addboot(source, target, env):
 | 
			
		||||
        from pathlib import Path
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/jgaurora_a5s_a1.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
        fw_path = Path(target[0].path)
 | 
			
		||||
        fwb_path = fw_path.parent / 'firmware_with_bootloader.bin'
 | 
			
		||||
        with fwb_path.open("wb") as fwb_file:
 | 
			
		||||
            bl_path = Path("buildroot/share/PlatformIO/scripts/jgaurora_bootloader.bin")
 | 
			
		||||
            bl_file = bl_path.open("rb")
 | 
			
		||||
            while True:
 | 
			
		||||
                b = bl_file.read(1)
 | 
			
		||||
                if b == b'': break
 | 
			
		||||
                else: fwb_file.write(b)
 | 
			
		||||
 | 
			
		||||
#append ${PROGNAME}.bin firmware after bootloader and save it as 'jgaurora_firmware.bin'
 | 
			
		||||
def addboot(source,target,env):
 | 
			
		||||
	firmware = open(target[0].path, "rb")
 | 
			
		||||
	lengthfirmware = os.path.getsize(target[0].path)
 | 
			
		||||
	bootloader_dir = "buildroot/share/PlatformIO/scripts/jgaurora_bootloader.bin"
 | 
			
		||||
	bootloader = open(bootloader_dir, "rb")
 | 
			
		||||
	lengthbootloader = os.path.getsize(bootloader_dir)
 | 
			
		||||
	firmware_with_boothloader_dir = target[0].dir.path +'/firmware_with_bootloader.bin'
 | 
			
		||||
	if os.path.exists(firmware_with_boothloader_dir):
 | 
			
		||||
		os.remove(firmware_with_boothloader_dir)
 | 
			
		||||
	firmwareimage = open(firmware_with_boothloader_dir, "wb")
 | 
			
		||||
	position = 0
 | 
			
		||||
	while position < lengthbootloader:
 | 
			
		||||
		byte = bootloader.read(1)
 | 
			
		||||
		firmwareimage.write(byte)
 | 
			
		||||
		position += 1
 | 
			
		||||
	position = 0
 | 
			
		||||
	while position < lengthfirmware:
 | 
			
		||||
		byte = firmware.read(1)
 | 
			
		||||
		firmwareimage.write(byte)
 | 
			
		||||
		position += 1
 | 
			
		||||
	bootloader.close()
 | 
			
		||||
	firmware.close()
 | 
			
		||||
	firmwareimage.close()
 | 
			
		||||
	firmware_without_bootloader_dir = target[0].dir.path+'/firmware_for_sd_upload.bin'
 | 
			
		||||
	if os.path.exists(firmware_without_bootloader_dir):
 | 
			
		||||
		os.remove(firmware_without_bootloader_dir)
 | 
			
		||||
	os.rename(target[0].path, firmware_without_bootloader_dir)
 | 
			
		||||
	#os.rename(target[0].dir.path+'/firmware_with_bootloader.bin', target[0].dir.path+'/firmware.bin')
 | 
			
		||||
            with fw_path.open("rb") as fw_file:
 | 
			
		||||
                while True:
 | 
			
		||||
                    b = fw_file.read(1)
 | 
			
		||||
                    if b == b'': break
 | 
			
		||||
                    else: fwb_file.write(b)
 | 
			
		||||
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", addboot);
 | 
			
		||||
        fws_path = Path(target[0].dir.path, 'firmware_for_sd_upload.bin')
 | 
			
		||||
        if fws_path.exists():
 | 
			
		||||
            fws_path.unlink()
 | 
			
		||||
 | 
			
		||||
        fw_path.rename(fws_path)
 | 
			
		||||
 | 
			
		||||
    import marlin
 | 
			
		||||
    marlin.add_post_action(addboot);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,46 +1,47 @@
 | 
			
		||||
import os,sys
 | 
			
		||||
Import("env")
 | 
			
		||||
#
 | 
			
		||||
# lerdge.py
 | 
			
		||||
# Customizations for Lerdge build environments:
 | 
			
		||||
#   env:LERDGEX  env:LERDGEX_usb_flash_drive
 | 
			
		||||
#   env:LERDGES  env:LERDGES_usb_flash_drive
 | 
			
		||||
#   env:LERDGEK  env:LERDGEK_usb_flash_drive
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    import os,marlin
 | 
			
		||||
 | 
			
		||||
from SCons.Script import DefaultEnvironment
 | 
			
		||||
board = DefaultEnvironment().BoardConfig()
 | 
			
		||||
    board = marlin.env.BoardConfig()
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/lerdge.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
    def encryptByte(byte):
 | 
			
		||||
        byte = 0xFF & ((byte << 6) | (byte >> 2))
 | 
			
		||||
        i = 0x58 + byte
 | 
			
		||||
        j = 0x05 + byte + (i >> 8)
 | 
			
		||||
        byte = (0xF8 & i) | (0x07 & j)
 | 
			
		||||
        return byte
 | 
			
		||||
 | 
			
		||||
def encryptByte(byte):
 | 
			
		||||
    byte = 0xFF & ((byte << 6) | (byte >> 2))
 | 
			
		||||
    i = 0x58 + byte
 | 
			
		||||
    j = 0x05 + byte + (i >> 8)
 | 
			
		||||
    byte = (0xF8 & i) | (0x07 & j)
 | 
			
		||||
    return byte
 | 
			
		||||
    def encrypt_file(input, output_file, file_length):
 | 
			
		||||
        input_file = bytearray(input.read())
 | 
			
		||||
        for i in range(len(input_file)):
 | 
			
		||||
            input_file[i] = encryptByte(input_file[i])
 | 
			
		||||
        output_file.write(input_file)
 | 
			
		||||
 | 
			
		||||
def encrypt_file(input, output_file, file_length):
 | 
			
		||||
    input_file = bytearray(input.read())
 | 
			
		||||
    for i in range(len(input_file)):
 | 
			
		||||
        result = encryptByte(input_file[i])
 | 
			
		||||
        input_file[i] = result
 | 
			
		||||
    # Encrypt ${PROGNAME}.bin and save it with the name given in build.crypt_lerdge
 | 
			
		||||
    def encrypt(source, target, env):
 | 
			
		||||
        fwpath = target[0].path
 | 
			
		||||
        enname = board.get("build.crypt_lerdge")
 | 
			
		||||
        print("Encrypting %s to %s" % (fwpath, enname))
 | 
			
		||||
        fwfile = open(fwpath, "rb")
 | 
			
		||||
        enfile = open(target[0].dir.path + "/" + enname, "wb")
 | 
			
		||||
        length = os.path.getsize(fwpath)
 | 
			
		||||
 | 
			
		||||
    output_file.write(input_file)
 | 
			
		||||
    return
 | 
			
		||||
        encrypt_file(fwfile, enfile, length)
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as build.firmware
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    print("Encrypting to:", board.get("build.firmware"))
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    result = open(target[0].dir.path + "/" + board.get("build.firmware"), "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
        fwfile.close()
 | 
			
		||||
        enfile.close()
 | 
			
		||||
        os.remove(fwpath)
 | 
			
		||||
 | 
			
		||||
    encrypt_file(firmware, result, length)
 | 
			
		||||
 | 
			
		||||
    firmware.close()
 | 
			
		||||
    result.close()
 | 
			
		||||
 | 
			
		||||
if 'firmware' in board.get("build").keys():
 | 
			
		||||
  env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
else:
 | 
			
		||||
  print("You need to define output file via board_build.firmware = 'filename' parameter")
 | 
			
		||||
  exit(1);
 | 
			
		||||
    if 'crypt_lerdge' in board.get("build").keys():
 | 
			
		||||
        if board.get("build.crypt_lerdge") != "":
 | 
			
		||||
            marlin.add_post_action(encrypt)
 | 
			
		||||
    else:
 | 
			
		||||
        print("LERDGE builds require output file via board_build.crypt_lerdge = 'filename' parameter")
 | 
			
		||||
        exit(1)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										72
									
								
								buildroot/share/PlatformIO/scripts/marlin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								buildroot/share/PlatformIO/scripts/marlin.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
			
		||||
#
 | 
			
		||||
# marlin.py
 | 
			
		||||
# Helper module with some commonly-used functions
 | 
			
		||||
#
 | 
			
		||||
import shutil
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
from SCons.Script import DefaultEnvironment
 | 
			
		||||
env = DefaultEnvironment()
 | 
			
		||||
 | 
			
		||||
def copytree(src, dst, symlinks=False, ignore=None):
 | 
			
		||||
    for item in src.iterdir():
 | 
			
		||||
        if item.is_dir():
 | 
			
		||||
            shutil.copytree(item, dst / item.name, symlinks, ignore)
 | 
			
		||||
        else:
 | 
			
		||||
            shutil.copy2(item, dst / item.name)
 | 
			
		||||
 | 
			
		||||
def replace_define(field, value):
 | 
			
		||||
    for define in env['CPPDEFINES']:
 | 
			
		||||
        if define[0] == field:
 | 
			
		||||
            env['CPPDEFINES'].remove(define)
 | 
			
		||||
    env['CPPDEFINES'].append((field, value))
 | 
			
		||||
 | 
			
		||||
# Relocate the firmware to a new address, such as "0x08005000"
 | 
			
		||||
def relocate_firmware(address):
 | 
			
		||||
    replace_define("VECT_TAB_ADDR", address)
 | 
			
		||||
 | 
			
		||||
# Relocate the vector table with a new offset
 | 
			
		||||
def relocate_vtab(address):
 | 
			
		||||
    replace_define("VECT_TAB_OFFSET", address)
 | 
			
		||||
 | 
			
		||||
# Replace the existing -Wl,-T with the given ldscript path
 | 
			
		||||
def custom_ld_script(ldname):
 | 
			
		||||
    apath = str(Path("buildroot/share/PlatformIO/ldscripts", ldname).resolve())
 | 
			
		||||
    for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
        if "-Wl,-T" in flag:
 | 
			
		||||
            env["LINKFLAGS"][i] = "-Wl,-T" + apath
 | 
			
		||||
        elif flag == "-T":
 | 
			
		||||
            env["LINKFLAGS"][i + 1] = apath
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it with a new name. This applies (mostly) to MKS boards
 | 
			
		||||
# This PostAction is set up by offset_and_rename.py for envs with 'build.encrypt_mks'.
 | 
			
		||||
def encrypt_mks(source, target, env, new_name):
 | 
			
		||||
    import sys
 | 
			
		||||
 | 
			
		||||
    key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
    # If FIRMWARE_BIN is defined by config, override all
 | 
			
		||||
    mf = env["MARLIN_FEATURES"]
 | 
			
		||||
    if "FIRMWARE_BIN" in mf: new_name = mf["FIRMWARE_BIN"]
 | 
			
		||||
 | 
			
		||||
    fwpath = Path(target[0].path)
 | 
			
		||||
    fwfile = fwpath.open("rb")
 | 
			
		||||
    enfile = Path(target[0].dir.path, new_name).open("wb")
 | 
			
		||||
    length = fwpath.stat().st_size
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = fwfile.read(1)
 | 
			
		||||
            if 320 <= position < 31040:
 | 
			
		||||
                byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
                if sys.version_info[0] > 2:
 | 
			
		||||
                    byte = bytes(byte, 'latin1')
 | 
			
		||||
            enfile.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        fwfile.close()
 | 
			
		||||
        enfile.close()
 | 
			
		||||
        fwpath.unlink()
 | 
			
		||||
 | 
			
		||||
def add_post_action(action):
 | 
			
		||||
    env.AddPostAction(str(Path("$BUILD_DIR", "${PROGNAME}.bin")), action);
 | 
			
		||||
							
								
								
									
										68
									
								
								buildroot/share/PlatformIO/scripts/mc-apply.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										68
									
								
								buildroot/share/PlatformIO/scripts/mc-apply.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#
 | 
			
		||||
# Create a Configuration from marlin_config.json
 | 
			
		||||
#
 | 
			
		||||
import json
 | 
			
		||||
import sys
 | 
			
		||||
import shutil
 | 
			
		||||
 | 
			
		||||
opt_output = '--opt' in sys.argv
 | 
			
		||||
output_suffix = '.sh' if opt_output else '' if '--bare-output' in sys.argv else '.gen'
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    with open('marlin_config.json', 'r') as infile:
 | 
			
		||||
        conf = json.load(infile)
 | 
			
		||||
        for key in conf:
 | 
			
		||||
            # We don't care about the hash when restoring here
 | 
			
		||||
            if key == '__INITIAL_HASH':
 | 
			
		||||
                continue
 | 
			
		||||
            if key == 'VERSION':
 | 
			
		||||
                for k, v in sorted(conf[key].items()):
 | 
			
		||||
                    print(k + ': ' + v)
 | 
			
		||||
                continue
 | 
			
		||||
            # The key is the file name, so let's build it now
 | 
			
		||||
            outfile = open('Marlin/' + key + output_suffix, 'w')
 | 
			
		||||
            for k, v in sorted(conf[key].items()):
 | 
			
		||||
                # Make define line now
 | 
			
		||||
                if opt_output:
 | 
			
		||||
                    if v != '':
 | 
			
		||||
                        if '"' in v:
 | 
			
		||||
                            v = "'%s'" % v
 | 
			
		||||
                        elif ' ' in v:
 | 
			
		||||
                            v = '"%s"' % v
 | 
			
		||||
                        define = 'opt_set ' + k + ' ' + v + '\n'
 | 
			
		||||
                    else:
 | 
			
		||||
                        define = 'opt_enable ' + k + '\n'
 | 
			
		||||
                else:
 | 
			
		||||
                    define = '#define ' + k + ' ' + v + '\n'
 | 
			
		||||
                outfile.write(define)
 | 
			
		||||
            outfile.close()
 | 
			
		||||
 | 
			
		||||
            # Try to apply changes to the actual configuration file (in order to keep useful comments)
 | 
			
		||||
            if output_suffix != '':
 | 
			
		||||
                # Move the existing configuration so it doesn't interfere
 | 
			
		||||
                shutil.move('Marlin/' + key, 'Marlin/' + key + '.orig')
 | 
			
		||||
                infile_lines = open('Marlin/' + key + '.orig', 'r').read().split('\n')
 | 
			
		||||
                outfile = open('Marlin/' + key, 'w')
 | 
			
		||||
                for line in infile_lines:
 | 
			
		||||
                    sline = line.strip(" \t\n\r")
 | 
			
		||||
                    if sline[:7] == "#define":
 | 
			
		||||
                        # Extract the key here (we don't care about the value)
 | 
			
		||||
                        kv = sline[8:].strip().split(' ')
 | 
			
		||||
                        if kv[0] in conf[key]:
 | 
			
		||||
                            outfile.write('#define ' + kv[0] + ' ' + conf[key][kv[0]] + '\n')
 | 
			
		||||
                            # Remove the key from the dict, so we can still write all missing keys at the end of the file
 | 
			
		||||
                            del conf[key][kv[0]]
 | 
			
		||||
                        else:
 | 
			
		||||
                            outfile.write(line + '\n')
 | 
			
		||||
                    else:
 | 
			
		||||
                        outfile.write(line + '\n')
 | 
			
		||||
                # Process any remaining defines here
 | 
			
		||||
                for k, v in sorted(conf[key].items()):
 | 
			
		||||
                    define = '#define ' + k + ' ' + v + '\n'
 | 
			
		||||
                    outfile.write(define)
 | 
			
		||||
                outfile.close()
 | 
			
		||||
 | 
			
		||||
            print('Output configuration written to: ' + 'Marlin/' + key + output_suffix)
 | 
			
		||||
except:
 | 
			
		||||
    print('No marlin_config.json found.')
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
import os,sys
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
from SCons.Script import DefaultEnvironment
 | 
			
		||||
board = DefaultEnvironment().BoardConfig()
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as build.firmware ('Robin.bin')
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
  key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
  firmware = open(target[0].path, "rb")
 | 
			
		||||
  robin = open(target[0].dir.path +'/'+ board.get("build.firmware"), "wb")
 | 
			
		||||
  length = os.path.getsize(target[0].path)
 | 
			
		||||
  position = 0
 | 
			
		||||
  try:
 | 
			
		||||
    while position < length:
 | 
			
		||||
      byte = firmware.read(1)
 | 
			
		||||
      if position >= 320 and position < 31040:
 | 
			
		||||
        byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
        if sys.version_info[0] > 2:
 | 
			
		||||
          byte = bytes(byte, 'latin1')
 | 
			
		||||
      robin.write(byte)
 | 
			
		||||
      position += 1
 | 
			
		||||
  finally:
 | 
			
		||||
    firmware.close()
 | 
			
		||||
    robin.close()
 | 
			
		||||
 | 
			
		||||
if 'firmware' in board.get("build").keys():
 | 
			
		||||
  env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
else:
 | 
			
		||||
  print("You need to define output file via board_build.firmware = 'filename' parameter", file=sys.stderr)
 | 
			
		||||
  exit(1);
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08007000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/mks_robin.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as 'Robin.bin'
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    import sys
 | 
			
		||||
 | 
			
		||||
    key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    robin = open(target[0].dir.path +'/Robin.bin', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = firmware.read(1)
 | 
			
		||||
            if position >= 320 and position < 31040:
 | 
			
		||||
                byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
                if sys.version_info[0] > 2:
 | 
			
		||||
                    byte = bytes(byte, 'latin1')
 | 
			
		||||
            robin.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        firmware.close()
 | 
			
		||||
        robin.close()
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08005000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08005000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/mks_robin_e3.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as 'mksLite.bin'
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    import sys
 | 
			
		||||
 | 
			
		||||
    key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    robin = open(target[0].dir.path +'/Robin_e3.bin', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = firmware.read(1)
 | 
			
		||||
            if position >= 320 and position < 31040:
 | 
			
		||||
                byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
                if sys.version_info[0] > 2:
 | 
			
		||||
                    byte = bytes(byte, 'latin1')
 | 
			
		||||
            robin.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        firmware.close()
 | 
			
		||||
        robin.close()
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08007000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/mks_robin_e3p.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as 'mks_robin_e3p.bin'
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    import sys
 | 
			
		||||
 | 
			
		||||
    key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    robin = open(target[0].dir.path +'/Robin_e3p.bin', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = firmware.read(1)
 | 
			
		||||
            if position >= 320 and position < 31040:
 | 
			
		||||
                byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
                if sys.version_info[0] > 2:
 | 
			
		||||
                    byte = bytes(byte, 'latin1')
 | 
			
		||||
            robin.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        firmware.close()
 | 
			
		||||
        robin.close()
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08005000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08005000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/mks_robin_lite.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as 'mksLite.bin'
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    import sys
 | 
			
		||||
 | 
			
		||||
    key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    robin = open(target[0].dir.path +'/mksLite.bin', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = firmware.read(1)
 | 
			
		||||
            if position >= 320 and position < 31040:
 | 
			
		||||
                byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
                if sys.version_info[0] > 2:
 | 
			
		||||
                    byte = bytes(byte, 'latin1')
 | 
			
		||||
            robin.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        firmware.close()
 | 
			
		||||
        robin.close()
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08005000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08005000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/mks_robin_lite.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as 'mksLite.bin'
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    import sys
 | 
			
		||||
 | 
			
		||||
    key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    robin = open(target[0].dir.path +'/mksLite3.bin', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = firmware.read(1)
 | 
			
		||||
            if position >= 320 and position < 31040:
 | 
			
		||||
                byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
                if sys.version_info[0] > 2:
 | 
			
		||||
                    byte = bytes(byte, 'latin1')
 | 
			
		||||
            robin.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        firmware.close()
 | 
			
		||||
        robin.close()
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08007000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/mks_robin_mini.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as 'Robin_mini.bin'
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    import sys
 | 
			
		||||
 | 
			
		||||
    key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    robin = open(target[0].dir.path +'/Robin_mini.bin', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = firmware.read(1)
 | 
			
		||||
            if position >= 320 and position < 31040:
 | 
			
		||||
                byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
                if sys.version_info[0] > 2:
 | 
			
		||||
                    byte = bytes(byte, 'latin1')
 | 
			
		||||
            robin.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        firmware.close()
 | 
			
		||||
        robin.close()
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08007000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/mks_robin_nano.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as 'Robin_nano.bin'
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    import sys
 | 
			
		||||
 | 
			
		||||
    key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    robin = open(target[0].dir.path +'/Robin_nano.bin', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = firmware.read(1)
 | 
			
		||||
            if position >= 320 and position < 31040:
 | 
			
		||||
                byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
                if sys.version_info[0] > 2:
 | 
			
		||||
                    byte = bytes(byte, 'latin1')
 | 
			
		||||
            robin.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        firmware.close()
 | 
			
		||||
        robin.close()
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08007000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/mks_robin_nano.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as 'Robin_nano35.bin'
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    import sys
 | 
			
		||||
 | 
			
		||||
    key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    robin = open(target[0].dir.path +'/Robin_nano35.bin', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = firmware.read(1)
 | 
			
		||||
            if position >= 320 and position < 31040:
 | 
			
		||||
                byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
                if sys.version_info[0] > 2:
 | 
			
		||||
                    byte = bytes(byte, 'latin1')
 | 
			
		||||
            robin.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        firmware.close()
 | 
			
		||||
        robin.close()
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
import os
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
# Relocate firmware from 0x08000000 to 0x08007000
 | 
			
		||||
for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_ADDR":
 | 
			
		||||
        env['CPPDEFINES'].remove(define)
 | 
			
		||||
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000"))
 | 
			
		||||
 | 
			
		||||
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/mks_robin_pro.ld")
 | 
			
		||||
for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,-T" in flag:
 | 
			
		||||
        env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script
 | 
			
		||||
    elif flag == "-T":
 | 
			
		||||
        env["LINKFLAGS"][i + 1] = custom_ld_script
 | 
			
		||||
 | 
			
		||||
# Encrypt ${PROGNAME}.bin and save it as 'Robin.bin'
 | 
			
		||||
def encrypt(source, target, env):
 | 
			
		||||
    import sys
 | 
			
		||||
 | 
			
		||||
    key = [0xA3, 0xBD, 0xAD, 0x0D, 0x41, 0x11, 0xBB, 0x8D, 0xDC, 0x80, 0x2D, 0xD0, 0xD2, 0xC4, 0x9B, 0x1E, 0x26, 0xEB, 0xE3, 0x33, 0x4A, 0x15, 0xE4, 0x0A, 0xB3, 0xB1, 0x3C, 0x93, 0xBB, 0xAF, 0xF7, 0x3E]
 | 
			
		||||
 | 
			
		||||
    firmware = open(target[0].path, "rb")
 | 
			
		||||
    robin = open(target[0].dir.path +'/Robin_pro.bin', "wb")
 | 
			
		||||
    length = os.path.getsize(target[0].path)
 | 
			
		||||
    position = 0
 | 
			
		||||
    try:
 | 
			
		||||
        while position < length:
 | 
			
		||||
            byte = firmware.read(1)
 | 
			
		||||
            if position >= 320 and position < 31040:
 | 
			
		||||
                byte = chr(ord(byte) ^ key[position & 31])
 | 
			
		||||
                if sys.version_info[0] > 2:
 | 
			
		||||
                    byte = bytes(byte, 'latin1')
 | 
			
		||||
            robin.write(byte)
 | 
			
		||||
            position += 1
 | 
			
		||||
    finally:
 | 
			
		||||
        firmware.close()
 | 
			
		||||
        robin.close()
 | 
			
		||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", encrypt);
 | 
			
		||||
							
								
								
									
										65
									
								
								buildroot/share/PlatformIO/scripts/offset_and_rename.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								buildroot/share/PlatformIO/scripts/offset_and_rename.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
#
 | 
			
		||||
# offset_and_rename.py
 | 
			
		||||
#
 | 
			
		||||
# - If 'build.offset' is provided, either by JSON or by the environment...
 | 
			
		||||
#   - Set linker flag LD_FLASH_OFFSET and relocate the VTAB based on 'build.offset'.
 | 
			
		||||
#   - Set linker flag LD_MAX_DATA_SIZE based on 'build.maximum_ram_size'.
 | 
			
		||||
#   - Define STM32_FLASH_SIZE from 'upload.maximum_size' for use by Flash-based EEPROM emulation.
 | 
			
		||||
#
 | 
			
		||||
# - For 'board_build.rename' add a post-action to rename the firmware file.
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    import marlin
 | 
			
		||||
 | 
			
		||||
    env = marlin.env
 | 
			
		||||
    board = env.BoardConfig()
 | 
			
		||||
    board_keys = board.get("build").keys()
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # For build.offset define LD_FLASH_OFFSET, used by ldscript.ld
 | 
			
		||||
    #
 | 
			
		||||
    if 'offset' in board_keys:
 | 
			
		||||
        LD_FLASH_OFFSET = board.get("build.offset")
 | 
			
		||||
        marlin.relocate_vtab(LD_FLASH_OFFSET)
 | 
			
		||||
 | 
			
		||||
        # Flash size
 | 
			
		||||
        maximum_flash_size = int(board.get("upload.maximum_size") / 1024)
 | 
			
		||||
        marlin.replace_define('STM32_FLASH_SIZE', maximum_flash_size)
 | 
			
		||||
 | 
			
		||||
        # Get upload.maximum_ram_size (defined by /buildroot/share/PlatformIO/boards/VARIOUS.json)
 | 
			
		||||
        maximum_ram_size = board.get("upload.maximum_ram_size")
 | 
			
		||||
 | 
			
		||||
        for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
            if "-Wl,--defsym=LD_FLASH_OFFSET" in flag:
 | 
			
		||||
                env["LINKFLAGS"][i] = "-Wl,--defsym=LD_FLASH_OFFSET=" + LD_FLASH_OFFSET
 | 
			
		||||
            if "-Wl,--defsym=LD_MAX_DATA_SIZE" in flag:
 | 
			
		||||
                env["LINKFLAGS"][i] = "-Wl,--defsym=LD_MAX_DATA_SIZE=" + str(maximum_ram_size - 40)
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # For build.encrypt_mks rename and encode the firmware file.
 | 
			
		||||
    #
 | 
			
		||||
    if 'encrypt_mks' in board_keys:
 | 
			
		||||
 | 
			
		||||
        # Encrypt ${PROGNAME}.bin and save it with the name given in build.encrypt_mks
 | 
			
		||||
        def encrypt(source, target, env):
 | 
			
		||||
            marlin.encrypt_mks(source, target, env, board.get("build.encrypt_mks"))
 | 
			
		||||
 | 
			
		||||
        if board.get("build.encrypt_mks") != "":
 | 
			
		||||
            marlin.add_post_action(encrypt)
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # For build.rename simply rename the firmware file.
 | 
			
		||||
    #
 | 
			
		||||
    if 'rename' in board_keys:
 | 
			
		||||
 | 
			
		||||
        # If FIRMWARE_BIN is defined by config, override all
 | 
			
		||||
        mf = env["MARLIN_FEATURES"]
 | 
			
		||||
        if "FIRMWARE_BIN" in mf: new_name = mf["FIRMWARE_BIN"]
 | 
			
		||||
        else: new_name = board.get("build.rename")
 | 
			
		||||
 | 
			
		||||
        def rename_target(source, target, env):
 | 
			
		||||
            from pathlib import Path
 | 
			
		||||
            Path(target[0].path).replace(Path(target[0].dir.path, new_name))
 | 
			
		||||
 | 
			
		||||
        marlin.add_post_action(rename_target)
 | 
			
		||||
							
								
								
									
										19
									
								
								buildroot/share/PlatformIO/scripts/openblt.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								buildroot/share/PlatformIO/scripts/openblt.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
#
 | 
			
		||||
# Convert the ELF to an SREC file suitable for some bootloaders
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    from os.path import join
 | 
			
		||||
 | 
			
		||||
    Import("env")
 | 
			
		||||
 | 
			
		||||
    board = env.BoardConfig()
 | 
			
		||||
    board_keys = board.get("build").keys()
 | 
			
		||||
    if 'encode' in board_keys:
 | 
			
		||||
        env.AddPostAction(
 | 
			
		||||
            join("$BUILD_DIR", "${PROGNAME}.bin"),
 | 
			
		||||
            env.VerboseAction(" ".join([
 | 
			
		||||
                "$OBJCOPY", "-O", "srec",
 | 
			
		||||
                "\"$BUILD_DIR/${PROGNAME}.elf\"", "\"" + join("$BUILD_DIR", board.get("build.encode")) + "\""
 | 
			
		||||
            ]), "Building " + board.get("build.encode"))
 | 
			
		||||
        )
 | 
			
		||||
							
								
								
									
										14
									
								
								buildroot/share/PlatformIO/scripts/pioutil.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								buildroot/share/PlatformIO/scripts/pioutil.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#
 | 
			
		||||
# pioutil.py
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# Make sure 'vscode init' is not the current command
 | 
			
		||||
def is_pio_build():
 | 
			
		||||
    from SCons.Script import DefaultEnvironment
 | 
			
		||||
    env = DefaultEnvironment()
 | 
			
		||||
    if "IsCleanTarget" in dir(env) and env.IsCleanTarget(): return False
 | 
			
		||||
    return not env.IsIntegrationDump()
 | 
			
		||||
 | 
			
		||||
def get_pio_version():
 | 
			
		||||
    from platformio import util
 | 
			
		||||
    return util.pioversion_to_intstr()
 | 
			
		||||
							
								
								
									
										127
									
								
								buildroot/share/PlatformIO/scripts/preflight-checks.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								buildroot/share/PlatformIO/scripts/preflight-checks.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,127 @@
 | 
			
		||||
#
 | 
			
		||||
# preflight-checks.py
 | 
			
		||||
# Check for common issues prior to compiling
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
 | 
			
		||||
    import re,sys
 | 
			
		||||
    from pathlib import Path
 | 
			
		||||
    Import("env")
 | 
			
		||||
 | 
			
		||||
    def get_envs_for_board(board):
 | 
			
		||||
        ppath = Path("Marlin/src/pins/pins.h")
 | 
			
		||||
        with ppath.open() as file:
 | 
			
		||||
 | 
			
		||||
            if sys.platform == 'win32':
 | 
			
		||||
                envregex = r"(?:env|win):"
 | 
			
		||||
            elif sys.platform == 'darwin':
 | 
			
		||||
                envregex = r"(?:env|mac|uni):"
 | 
			
		||||
            elif sys.platform == 'linux':
 | 
			
		||||
                envregex = r"(?:env|lin|uni):"
 | 
			
		||||
            else:
 | 
			
		||||
                envregex = r"(?:env):"
 | 
			
		||||
 | 
			
		||||
            r = re.compile(r"if\s+MB\((.+)\)")
 | 
			
		||||
            if board.startswith("BOARD_"):
 | 
			
		||||
                board = board[6:]
 | 
			
		||||
 | 
			
		||||
            for line in file:
 | 
			
		||||
                mbs = r.findall(line)
 | 
			
		||||
                if mbs and board in re.split(r",\s*", mbs[0]):
 | 
			
		||||
                    line = file.readline()
 | 
			
		||||
                    found_envs = re.match(r"\s*#include .+" + envregex, line)
 | 
			
		||||
                    if found_envs:
 | 
			
		||||
                        envlist = re.findall(envregex + r"(\w+)", line)
 | 
			
		||||
                        return [ "env:"+s for s in envlist ]
 | 
			
		||||
        return []
 | 
			
		||||
 | 
			
		||||
    def check_envs(build_env, board_envs, config):
 | 
			
		||||
        if build_env in board_envs:
 | 
			
		||||
            return True
 | 
			
		||||
        ext = config.get(build_env, 'extends', default=None)
 | 
			
		||||
        if ext:
 | 
			
		||||
            if isinstance(ext, str):
 | 
			
		||||
                return check_envs(ext, board_envs, config)
 | 
			
		||||
            elif isinstance(ext, list):
 | 
			
		||||
                for ext_env in ext:
 | 
			
		||||
                    if check_envs(ext_env, board_envs, config):
 | 
			
		||||
                        return True
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    def sanity_check_target():
 | 
			
		||||
        # Sanity checks:
 | 
			
		||||
        if 'PIOENV' not in env:
 | 
			
		||||
            raise SystemExit("Error: PIOENV is not defined. This script is intended to be used with PlatformIO")
 | 
			
		||||
 | 
			
		||||
        # Require PlatformIO 6.1.1 or later
 | 
			
		||||
        vers = pioutil.get_pio_version()
 | 
			
		||||
        if vers < [6, 1, 1]:
 | 
			
		||||
            raise SystemExit("Error: Marlin requires PlatformIO >= 6.1.1. Use 'pio upgrade' to get a newer version.")
 | 
			
		||||
 | 
			
		||||
        if 'MARLIN_FEATURES' not in env:
 | 
			
		||||
            raise SystemExit("Error: this script should be used after common Marlin scripts.")
 | 
			
		||||
 | 
			
		||||
        if len(env['MARLIN_FEATURES']) == 0:
 | 
			
		||||
            raise SystemExit("Error: Failed to parse Marlin features. See previous error messages.")
 | 
			
		||||
 | 
			
		||||
        build_env = env['PIOENV']
 | 
			
		||||
        motherboard = env['MARLIN_FEATURES']['MOTHERBOARD']
 | 
			
		||||
        board_envs = get_envs_for_board(motherboard)
 | 
			
		||||
        config = env.GetProjectConfig()
 | 
			
		||||
        result = check_envs("env:"+build_env, board_envs, config)
 | 
			
		||||
 | 
			
		||||
        if not result:
 | 
			
		||||
            err = "Error: Build environment '%s' is incompatible with %s. Use one of these: %s" % \
 | 
			
		||||
                  ( build_env, motherboard, ", ".join([ e[4:] for e in board_envs if e.startswith("env:") ]) )
 | 
			
		||||
            raise SystemExit(err)
 | 
			
		||||
 | 
			
		||||
        #
 | 
			
		||||
        # Check for Config files in two common incorrect places
 | 
			
		||||
        #
 | 
			
		||||
        epath = Path(env['PROJECT_DIR'])
 | 
			
		||||
        for p in [ epath, epath / "config" ]:
 | 
			
		||||
            for f in ("Configuration.h", "Configuration_adv.h"):
 | 
			
		||||
                if (p / f).is_file():
 | 
			
		||||
                    err = "ERROR: Config files found in directory %s. Please move them into the Marlin subfolder." % p
 | 
			
		||||
                    raise SystemExit(err)
 | 
			
		||||
 | 
			
		||||
        #
 | 
			
		||||
        # Find the name.cpp.o or name.o and remove it
 | 
			
		||||
        #
 | 
			
		||||
        def rm_ofile(subdir, name):
 | 
			
		||||
            build_dir = Path(env['PROJECT_BUILD_DIR'], build_env);
 | 
			
		||||
            for outdir in (build_dir, build_dir / "debug"):
 | 
			
		||||
                for ext in (".cpp.o", ".o"):
 | 
			
		||||
                    fpath = outdir / "src/src" / subdir / (name + ext)
 | 
			
		||||
                    if fpath.exists():
 | 
			
		||||
                        fpath.unlink()
 | 
			
		||||
 | 
			
		||||
        #
 | 
			
		||||
        # Give warnings on every build
 | 
			
		||||
        #
 | 
			
		||||
        rm_ofile("inc", "Warnings")
 | 
			
		||||
 | 
			
		||||
        #
 | 
			
		||||
        # Rebuild 'settings.cpp' for EEPROM_INIT_NOW
 | 
			
		||||
        #
 | 
			
		||||
        if 'EEPROM_INIT_NOW' in env['MARLIN_FEATURES']:
 | 
			
		||||
            rm_ofile("module", "settings")
 | 
			
		||||
 | 
			
		||||
        #
 | 
			
		||||
        # Check for old files indicating an entangled Marlin (mixing old and new code)
 | 
			
		||||
        #
 | 
			
		||||
        mixedin = []
 | 
			
		||||
        p = Path(env['PROJECT_DIR'], "Marlin/src/lcd/dogm")
 | 
			
		||||
        for f in [ "ultralcd_DOGM.cpp", "ultralcd_DOGM.h" ]:
 | 
			
		||||
            if (p / f).is_file():
 | 
			
		||||
                mixedin += [ f ]
 | 
			
		||||
        p = Path(env['PROJECT_DIR'], "Marlin/src/feature/bedlevel/abl")
 | 
			
		||||
        for f in [ "abl.cpp", "abl.h" ]:
 | 
			
		||||
            if (p / f).is_file():
 | 
			
		||||
                mixedin += [ f ]
 | 
			
		||||
        if mixedin:
 | 
			
		||||
            err = "ERROR: Old files fell into your Marlin folder. Remove %s and try again" % ", ".join(mixedin)
 | 
			
		||||
            raise SystemExit(err)
 | 
			
		||||
 | 
			
		||||
    sanity_check_target()
 | 
			
		||||
							
								
								
									
										94
									
								
								buildroot/share/PlatformIO/scripts/preprocessor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								buildroot/share/PlatformIO/scripts/preprocessor.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
			
		||||
#
 | 
			
		||||
# preprocessor.py
 | 
			
		||||
#
 | 
			
		||||
import subprocess
 | 
			
		||||
 | 
			
		||||
nocache = 1
 | 
			
		||||
verbose = 0
 | 
			
		||||
 | 
			
		||||
def blab(str):
 | 
			
		||||
    if verbose:
 | 
			
		||||
        print(str)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
# Invoke GCC to run the preprocessor and extract enabled features
 | 
			
		||||
#
 | 
			
		||||
preprocessor_cache = {}
 | 
			
		||||
def run_preprocessor(env, fn=None):
 | 
			
		||||
    filename = fn or 'buildroot/share/PlatformIO/scripts/common-dependencies.h'
 | 
			
		||||
    if filename in preprocessor_cache:
 | 
			
		||||
        return preprocessor_cache[filename]
 | 
			
		||||
 | 
			
		||||
    # Process defines
 | 
			
		||||
    build_flags = env.get('BUILD_FLAGS')
 | 
			
		||||
    build_flags = env.ParseFlagsExtended(build_flags)
 | 
			
		||||
 | 
			
		||||
    cxx = search_compiler(env)
 | 
			
		||||
    cmd = ['"' + cxx + '"']
 | 
			
		||||
 | 
			
		||||
    # Build flags from board.json
 | 
			
		||||
    #if 'BOARD' in env:
 | 
			
		||||
    #   cmd += [env.BoardConfig().get("build.extra_flags")]
 | 
			
		||||
    for s in build_flags['CPPDEFINES']:
 | 
			
		||||
        if isinstance(s, tuple):
 | 
			
		||||
            cmd += ['-D' + s[0] + '=' + str(s[1])]
 | 
			
		||||
        else:
 | 
			
		||||
            cmd += ['-D' + s]
 | 
			
		||||
 | 
			
		||||
    cmd += ['-D__MARLIN_DEPS__ -w -dM -E -x c++']
 | 
			
		||||
    depcmd = cmd + [ filename ]
 | 
			
		||||
    cmd = ' '.join(depcmd)
 | 
			
		||||
    blab(cmd)
 | 
			
		||||
    try:
 | 
			
		||||
        define_list = subprocess.check_output(cmd, shell=True).splitlines()
 | 
			
		||||
    except:
 | 
			
		||||
        define_list = {}
 | 
			
		||||
    preprocessor_cache[filename] = define_list
 | 
			
		||||
    return define_list
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
# Find a compiler, considering the OS
 | 
			
		||||
#
 | 
			
		||||
def search_compiler(env):
 | 
			
		||||
 | 
			
		||||
    from pathlib import Path, PurePath
 | 
			
		||||
 | 
			
		||||
    ENV_BUILD_PATH = Path(env['PROJECT_BUILD_DIR'], env['PIOENV'])
 | 
			
		||||
    GCC_PATH_CACHE = ENV_BUILD_PATH / ".gcc_path"
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        gccpath = env.GetProjectOption('custom_gcc')
 | 
			
		||||
        blab("Getting compiler from env")
 | 
			
		||||
        return gccpath
 | 
			
		||||
    except:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    # Warning: The cached .gcc_path will obscure a newly-installed toolkit
 | 
			
		||||
    if not nocache and GCC_PATH_CACHE.exists():
 | 
			
		||||
        blab("Getting g++ path from cache")
 | 
			
		||||
        return GCC_PATH_CACHE.read_text()
 | 
			
		||||
 | 
			
		||||
    # Use any item in $PATH corresponding to a platformio toolchain bin folder
 | 
			
		||||
    path_separator = ':'
 | 
			
		||||
    gcc_exe = '*g++'
 | 
			
		||||
    if env['PLATFORM'] == 'win32':
 | 
			
		||||
        path_separator = ';'
 | 
			
		||||
        gcc_exe += ".exe"
 | 
			
		||||
 | 
			
		||||
    # Search for the compiler in PATH
 | 
			
		||||
    for ppath in map(Path, env['ENV']['PATH'].split(path_separator)):
 | 
			
		||||
        if ppath.match(env['PROJECT_PACKAGES_DIR'] + "/**/bin"):
 | 
			
		||||
            for gpath in ppath.glob(gcc_exe):
 | 
			
		||||
                gccpath = str(gpath.resolve())
 | 
			
		||||
                # Cache the g++ path to no search always
 | 
			
		||||
                if not nocache and ENV_BUILD_PATH.exists():
 | 
			
		||||
                    blab("Caching g++ for current env")
 | 
			
		||||
                    GCC_PATH_CACHE.write_text(gccpath)
 | 
			
		||||
                return gccpath
 | 
			
		||||
 | 
			
		||||
    gccpath = env.get('CXX')
 | 
			
		||||
    blab("Couldn't find a compiler! Fallback to %s" % gccpath)
 | 
			
		||||
    return gccpath
 | 
			
		||||
@@ -1,5 +1,9 @@
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
 | 
			
		||||
env['PROGNAME'] = datetime.now().strftime("firmware-%Y%m%d-%H%M%S")
 | 
			
		||||
#
 | 
			
		||||
# random-bin.py
 | 
			
		||||
# Set a unique firmware name based on current date and time
 | 
			
		||||
#
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    from datetime import datetime
 | 
			
		||||
    Import("env")
 | 
			
		||||
    env['PROGNAME'] = datetime.now().strftime("firmware-%Y%m%d-%H%M%S")
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										421
									
								
								buildroot/share/PlatformIO/scripts/schema.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										421
									
								
								buildroot/share/PlatformIO/scripts/schema.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,421 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
#
 | 
			
		||||
# schema.py
 | 
			
		||||
#
 | 
			
		||||
# Used by signature.py via common-dependencies.py to generate a schema file during the PlatformIO build.
 | 
			
		||||
# This script can also be run standalone from within the Marlin repo to generate all schema files.
 | 
			
		||||
#
 | 
			
		||||
import re,json
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
def extend_dict(d:dict, k:tuple):
 | 
			
		||||
    if len(k) >= 1 and k[0] not in d:
 | 
			
		||||
        d[k[0]] = {}
 | 
			
		||||
    if len(k) >= 2 and k[1] not in d[k[0]]:
 | 
			
		||||
        d[k[0]][k[1]] = {}
 | 
			
		||||
    if len(k) >= 3 and k[2] not in d[k[0]][k[1]]:
 | 
			
		||||
        d[k[0]][k[1]][k[2]] = {}
 | 
			
		||||
 | 
			
		||||
grouping_patterns = [
 | 
			
		||||
    re.compile(r'^([XYZIJKUVW]|[XYZ]2|Z[34]|E[0-7])$'),
 | 
			
		||||
    re.compile(r'^AXIS\d$'),
 | 
			
		||||
    re.compile(r'^(MIN|MAX)$'),
 | 
			
		||||
    re.compile(r'^[0-8]$'),
 | 
			
		||||
    re.compile(r'^HOTEND[0-7]$'),
 | 
			
		||||
    re.compile(r'^(HOTENDS|BED|PROBE|COOLER)$'),
 | 
			
		||||
    re.compile(r'^[XYZIJKUVW]M(IN|AX)$')
 | 
			
		||||
]
 | 
			
		||||
# If the indexed part of the option name matches a pattern
 | 
			
		||||
# then add it to the dictionary.
 | 
			
		||||
def find_grouping(gdict, filekey, sectkey, optkey, pindex):
 | 
			
		||||
    optparts = optkey.split('_')
 | 
			
		||||
    if 1 < len(optparts) > pindex:
 | 
			
		||||
        for patt in grouping_patterns:
 | 
			
		||||
            if patt.match(optparts[pindex]):
 | 
			
		||||
                subkey = optparts[pindex]
 | 
			
		||||
                modkey = '_'.join(optparts)
 | 
			
		||||
                optparts[pindex] = '*'
 | 
			
		||||
                wildkey = '_'.join(optparts)
 | 
			
		||||
                kkey = f'{filekey}|{sectkey}|{wildkey}'
 | 
			
		||||
                if kkey not in gdict: gdict[kkey] = []
 | 
			
		||||
                gdict[kkey].append((subkey, modkey))
 | 
			
		||||
 | 
			
		||||
# Build a list of potential groups. Only those with multiple items will be grouped.
 | 
			
		||||
def group_options(schema):
 | 
			
		||||
    for pindex in range(10, -1, -1):
 | 
			
		||||
        found_groups = {}
 | 
			
		||||
        for filekey, f in schema.items():
 | 
			
		||||
            for sectkey, s in f.items():
 | 
			
		||||
                for optkey in s:
 | 
			
		||||
                    find_grouping(found_groups, filekey, sectkey, optkey, pindex)
 | 
			
		||||
 | 
			
		||||
        fkeys = [ k for k in found_groups.keys() ]
 | 
			
		||||
        for kkey in fkeys:
 | 
			
		||||
            items = found_groups[kkey]
 | 
			
		||||
            if len(items) > 1:
 | 
			
		||||
                f, s, w = kkey.split('|')
 | 
			
		||||
                extend_dict(schema, (f, s, w))                      # Add wildcard group to schema
 | 
			
		||||
                for subkey, optkey in items:                        # Add all items to wildcard group
 | 
			
		||||
                    schema[f][s][w][subkey] = schema[f][s][optkey]  # Move non-wildcard item to wildcard group
 | 
			
		||||
                    del schema[f][s][optkey]
 | 
			
		||||
            del found_groups[kkey]
 | 
			
		||||
 | 
			
		||||
# Extract all board names from boards.h
 | 
			
		||||
def load_boards():
 | 
			
		||||
    bpath = Path("Marlin/src/core/boards.h")
 | 
			
		||||
    if bpath.is_file():
 | 
			
		||||
        with bpath.open() as bfile:
 | 
			
		||||
            boards = []
 | 
			
		||||
            for line in bfile:
 | 
			
		||||
                if line.startswith("#define BOARD_"):
 | 
			
		||||
                    bname = line.split()[1]
 | 
			
		||||
                    if bname != "BOARD_UNKNOWN": boards.append(bname)
 | 
			
		||||
            return "['" + "','".join(boards) + "']"
 | 
			
		||||
    return ''
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Extract a schema from the current configuration files
 | 
			
		||||
#
 | 
			
		||||
def extract():
 | 
			
		||||
    # Load board names from boards.h
 | 
			
		||||
    boards = load_boards()
 | 
			
		||||
 | 
			
		||||
    # Parsing states
 | 
			
		||||
    class Parse:
 | 
			
		||||
        NORMAL          = 0 # No condition yet
 | 
			
		||||
        BLOCK_COMMENT   = 1 # Looking for the end of the block comment
 | 
			
		||||
        EOL_COMMENT     = 2 # EOL comment started, maybe add the next comment?
 | 
			
		||||
        GET_SENSORS     = 3 # Gathering temperature sensor options
 | 
			
		||||
        ERROR           = 9 # Syntax error
 | 
			
		||||
 | 
			
		||||
    # List of files to process, with shorthand
 | 
			
		||||
    filekey = { 'Configuration.h':'basic', 'Configuration_adv.h':'advanced' }
 | 
			
		||||
    # A JSON object to store the data
 | 
			
		||||
    sch_out = { 'basic':{}, 'advanced':{} }
 | 
			
		||||
    # Regex for #define NAME [VALUE] [COMMENT] with sanitized line
 | 
			
		||||
    defgrep = re.compile(r'^(//)?\s*(#define)\s+([A-Za-z0-9_]+)\s*(.*?)\s*(//.+)?$')
 | 
			
		||||
    # Defines to ignore
 | 
			
		||||
    ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXAMPLES_DIR', 'CONFIG_EXPORT')
 | 
			
		||||
    # Start with unknown state
 | 
			
		||||
    state = Parse.NORMAL
 | 
			
		||||
    # Serial ID
 | 
			
		||||
    sid = 0
 | 
			
		||||
    # Loop through files and parse them line by line
 | 
			
		||||
    for fn, fk in filekey.items():
 | 
			
		||||
        with Path("Marlin", fn).open() as fileobj:
 | 
			
		||||
            section = 'none'        # Current Settings section
 | 
			
		||||
            line_number = 0         # Counter for the line number of the file
 | 
			
		||||
            conditions = []         # Create a condition stack for the current file
 | 
			
		||||
            comment_buff = []       # A temporary buffer for comments
 | 
			
		||||
            options_json = ''       # A buffer for the most recent options JSON found
 | 
			
		||||
            eol_options = False     # The options came from end of line, so only apply once
 | 
			
		||||
            join_line = False       # A flag that the line should be joined with the previous one
 | 
			
		||||
            line = ''               # A line buffer to handle \ continuation
 | 
			
		||||
            last_added_ref = None   # Reference to the last added item
 | 
			
		||||
            # Loop through the lines in the file
 | 
			
		||||
            for the_line in fileobj.readlines():
 | 
			
		||||
                line_number += 1
 | 
			
		||||
 | 
			
		||||
                # Clean the line for easier parsing
 | 
			
		||||
                the_line = the_line.strip()
 | 
			
		||||
 | 
			
		||||
                if join_line:   # A previous line is being made longer
 | 
			
		||||
                    line += (' ' if line else '') + the_line
 | 
			
		||||
                else:           # Otherwise, start the line anew
 | 
			
		||||
                    line, line_start = the_line, line_number
 | 
			
		||||
 | 
			
		||||
                # If the resulting line ends with a \, don't process now.
 | 
			
		||||
                # Strip the end off. The next line will be joined with it.
 | 
			
		||||
                join_line = line.endswith("\\")
 | 
			
		||||
                if join_line:
 | 
			
		||||
                    line = line[:-1].strip()
 | 
			
		||||
                    continue
 | 
			
		||||
                else:
 | 
			
		||||
                    line_end = line_number
 | 
			
		||||
 | 
			
		||||
                defmatch = defgrep.match(line)
 | 
			
		||||
 | 
			
		||||
                # Special handling for EOL comments after a #define.
 | 
			
		||||
                # At this point the #define is already digested and inserted,
 | 
			
		||||
                # so we have to extend it
 | 
			
		||||
                if state == Parse.EOL_COMMENT:
 | 
			
		||||
                    # If the line is not a comment, we're done with the EOL comment
 | 
			
		||||
                    if not defmatch and the_line.startswith('//'):
 | 
			
		||||
                        comment_buff.append(the_line[2:].strip())
 | 
			
		||||
                    else:
 | 
			
		||||
                        last_added_ref['comment'] = ' '.join(comment_buff)
 | 
			
		||||
                        comment_buff = []
 | 
			
		||||
                        state = Parse.NORMAL
 | 
			
		||||
 | 
			
		||||
                def use_comment(c, opt, sec, bufref):
 | 
			
		||||
                    if c.startswith(':'):               # If the comment starts with : then it has magic JSON
 | 
			
		||||
                        d = c[1:].strip()               # Strip the leading :
 | 
			
		||||
                        cbr = c.rindex('}') if d.startswith('{') else c.rindex(']') if d.startswith('[') else 0
 | 
			
		||||
                        if cbr:
 | 
			
		||||
                            opt, cmt = c[1:cbr+1].strip(), c[cbr+1:].strip()
 | 
			
		||||
                            if cmt != '': bufref.append(cmt)
 | 
			
		||||
                        else:
 | 
			
		||||
                            opt = c[1:].strip()
 | 
			
		||||
                    elif c.startswith('@section'):      # Start a new section
 | 
			
		||||
                        sec = c[8:].strip()
 | 
			
		||||
                    elif not c.startswith('========'):
 | 
			
		||||
                        bufref.append(c)
 | 
			
		||||
                    return opt, sec
 | 
			
		||||
 | 
			
		||||
                # In a block comment, capture lines up to the end of the comment.
 | 
			
		||||
                # Assume nothing follows the comment closure.
 | 
			
		||||
                if state in (Parse.BLOCK_COMMENT, Parse.GET_SENSORS):
 | 
			
		||||
                    endpos = line.find('*/')
 | 
			
		||||
                    if endpos < 0:
 | 
			
		||||
                        cline = line
 | 
			
		||||
                    else:
 | 
			
		||||
                        cline, line = line[:endpos].strip(), line[endpos+2:].strip()
 | 
			
		||||
 | 
			
		||||
                        # Temperature sensors are done
 | 
			
		||||
                        if state == Parse.GET_SENSORS:
 | 
			
		||||
                            options_json = f'[ {options_json[:-2]} ]'
 | 
			
		||||
 | 
			
		||||
                        state = Parse.NORMAL
 | 
			
		||||
 | 
			
		||||
                    # Strip the leading '*' from block comments
 | 
			
		||||
                    if cline.startswith('*'): cline = cline[1:].strip()
 | 
			
		||||
 | 
			
		||||
                    # Collect temperature sensors
 | 
			
		||||
                    if state == Parse.GET_SENSORS:
 | 
			
		||||
                        sens = re.match(r'^(-?\d+)\s*:\s*(.+)$', cline)
 | 
			
		||||
                        if sens:
 | 
			
		||||
                            s2 = sens[2].replace("'","''")
 | 
			
		||||
                            options_json += f"{sens[1]}:'{s2}', "
 | 
			
		||||
 | 
			
		||||
                    elif state == Parse.BLOCK_COMMENT:
 | 
			
		||||
 | 
			
		||||
                        # Look for temperature sensors
 | 
			
		||||
                        if cline == "Temperature sensors available:":
 | 
			
		||||
                            state, cline = Parse.GET_SENSORS, "Temperature Sensors"
 | 
			
		||||
 | 
			
		||||
                        options_json, section = use_comment(cline, options_json, section, comment_buff)
 | 
			
		||||
 | 
			
		||||
                # For the normal state we're looking for any non-blank line
 | 
			
		||||
                elif state == Parse.NORMAL:
 | 
			
		||||
                    # Skip a commented define when evaluating comment opening
 | 
			
		||||
                    st = 2 if re.match(r'^//\s*#define', line) else 0
 | 
			
		||||
                    cpos1 = line.find('/*')     # Start a block comment on the line?
 | 
			
		||||
                    cpos2 = line.find('//', st) # Start an end of line comment on the line?
 | 
			
		||||
 | 
			
		||||
                    # Only the first comment starter gets evaluated
 | 
			
		||||
                    cpos = -1
 | 
			
		||||
                    if cpos1 != -1 and (cpos1 < cpos2 or cpos2 == -1):
 | 
			
		||||
                        cpos = cpos1
 | 
			
		||||
                        comment_buff = []
 | 
			
		||||
                        state = Parse.BLOCK_COMMENT
 | 
			
		||||
                        eol_options = False
 | 
			
		||||
 | 
			
		||||
                    elif cpos2 != -1 and (cpos2 < cpos1 or cpos1 == -1):
 | 
			
		||||
                        cpos = cpos2
 | 
			
		||||
 | 
			
		||||
                        # Comment after a define may be continued on the following lines
 | 
			
		||||
                        if defmatch != None and cpos > 10:
 | 
			
		||||
                            state = Parse.EOL_COMMENT
 | 
			
		||||
                            comment_buff = []
 | 
			
		||||
 | 
			
		||||
                    # Process the start of a new comment
 | 
			
		||||
                    if cpos != -1:
 | 
			
		||||
                        cline, line = line[cpos+2:].strip(), line[:cpos].strip()
 | 
			
		||||
 | 
			
		||||
                        if state == Parse.BLOCK_COMMENT:
 | 
			
		||||
                            # Strip leading '*' from block comments
 | 
			
		||||
                            if cline.startswith('*'): cline = cline[1:].strip()
 | 
			
		||||
                        else:
 | 
			
		||||
                            # Expire end-of-line options after first use
 | 
			
		||||
                            if cline.startswith(':'): eol_options = True
 | 
			
		||||
 | 
			
		||||
                        # Buffer a non-empty comment start
 | 
			
		||||
                        if cline != '':
 | 
			
		||||
                            options_json, section = use_comment(cline, options_json, section, comment_buff)
 | 
			
		||||
 | 
			
		||||
                    # If the line has nothing before the comment, go to the next line
 | 
			
		||||
                    if line == '':
 | 
			
		||||
                        options_json = ''
 | 
			
		||||
                        continue
 | 
			
		||||
 | 
			
		||||
                    # Parenthesize the given expression if needed
 | 
			
		||||
                    def atomize(s):
 | 
			
		||||
                        if s == '' \
 | 
			
		||||
                        or re.match(r'^[A-Za-z0-9_]*(\([^)]+\))?$', s) \
 | 
			
		||||
                        or re.match(r'^[A-Za-z0-9_]+ == \d+?$', s):
 | 
			
		||||
                            return s
 | 
			
		||||
                        return f'({s})'
 | 
			
		||||
 | 
			
		||||
                    #
 | 
			
		||||
                    # The conditions stack is an array containing condition-arrays.
 | 
			
		||||
                    # Each condition-array lists the conditions for the current block.
 | 
			
		||||
                    # IF/N/DEF adds a new condition-array to the stack.
 | 
			
		||||
                    # ELSE/ELIF/ENDIF pop the condition-array.
 | 
			
		||||
                    # ELSE/ELIF negate the last item in the popped condition-array.
 | 
			
		||||
                    # ELIF adds a new condition to the end of the array.
 | 
			
		||||
                    # ELSE/ELIF re-push the condition-array.
 | 
			
		||||
                    #
 | 
			
		||||
                    cparts = line.split()
 | 
			
		||||
                    iselif, iselse = cparts[0] == '#elif', cparts[0] == '#else'
 | 
			
		||||
                    if iselif or iselse or cparts[0] == '#endif':
 | 
			
		||||
                        if len(conditions) == 0:
 | 
			
		||||
                            raise Exception(f'no #if block at line {line_number}')
 | 
			
		||||
 | 
			
		||||
                        # Pop the last condition-array from the stack
 | 
			
		||||
                        prev = conditions.pop()
 | 
			
		||||
 | 
			
		||||
                        if iselif or iselse:
 | 
			
		||||
                            prev[-1] = '!' + prev[-1] # Invert the last condition
 | 
			
		||||
                            if iselif: prev.append(atomize(line[5:].strip()))
 | 
			
		||||
                            conditions.append(prev)
 | 
			
		||||
 | 
			
		||||
                    elif cparts[0] == '#if':
 | 
			
		||||
                        conditions.append([ atomize(line[3:].strip()) ])
 | 
			
		||||
                    elif cparts[0] == '#ifdef':
 | 
			
		||||
                        conditions.append([ f'defined({line[6:].strip()})' ])
 | 
			
		||||
                    elif cparts[0] == '#ifndef':
 | 
			
		||||
                        conditions.append([ f'!defined({line[7:].strip()})' ])
 | 
			
		||||
 | 
			
		||||
                    # Handle a complete #define line
 | 
			
		||||
                    elif defmatch != None:
 | 
			
		||||
 | 
			
		||||
                        # Get the match groups into vars
 | 
			
		||||
                        enabled, define_name, val = defmatch[1] == None, defmatch[3], defmatch[4]
 | 
			
		||||
 | 
			
		||||
                        # Increment the serial ID
 | 
			
		||||
                        sid += 1
 | 
			
		||||
 | 
			
		||||
                        # Create a new dictionary for the current #define
 | 
			
		||||
                        define_info = {
 | 
			
		||||
                            'section': section,
 | 
			
		||||
                            'name': define_name,
 | 
			
		||||
                            'enabled': enabled,
 | 
			
		||||
                            'line': line_start,
 | 
			
		||||
                            'sid': sid
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        # Type is based on the value
 | 
			
		||||
                        if val == '':
 | 
			
		||||
                            value_type = 'switch'
 | 
			
		||||
                        elif re.match(r'^(true|false)$', val):
 | 
			
		||||
                            value_type = 'bool'
 | 
			
		||||
                            val = val == 'true'
 | 
			
		||||
                        elif re.match(r'^[-+]?\s*\d+$', val):
 | 
			
		||||
                            value_type = 'int'
 | 
			
		||||
                            val = int(val)
 | 
			
		||||
                        elif re.match(r'[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?', val):
 | 
			
		||||
                            value_type = 'float'
 | 
			
		||||
                            val = float(val.replace('f',''))
 | 
			
		||||
                        else:
 | 
			
		||||
                            value_type = 'string'   if val[0] == '"' \
 | 
			
		||||
                                    else 'char'     if val[0] == "'" \
 | 
			
		||||
                                    else 'state'    if re.match(r'^(LOW|HIGH)$', val) \
 | 
			
		||||
                                    else 'enum'     if re.match(r'^[A-Za-z0-9_]{3,}$', val) \
 | 
			
		||||
                                    else 'int[]'    if re.match(r'^{(\s*[-+]?\s*\d+\s*(,\s*)?)+}$', val) \
 | 
			
		||||
                                    else 'float[]'  if re.match(r'^{(\s*[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?\s*(,\s*)?)+}$', val) \
 | 
			
		||||
                                    else 'array'    if val[0] == '{' \
 | 
			
		||||
                                    else ''
 | 
			
		||||
 | 
			
		||||
                        if val != '': define_info['value'] = val
 | 
			
		||||
                        if value_type != '': define_info['type'] = value_type
 | 
			
		||||
 | 
			
		||||
                        # Join up accumulated conditions with &&
 | 
			
		||||
                        if conditions: define_info['requires'] = ' && '.join(sum(conditions, []))
 | 
			
		||||
 | 
			
		||||
                        # If the comment_buff is not empty, add the comment to the info
 | 
			
		||||
                        if comment_buff:
 | 
			
		||||
                            full_comment = '\n'.join(comment_buff)
 | 
			
		||||
 | 
			
		||||
                            # An EOL comment will be added later
 | 
			
		||||
                            # The handling could go here instead of above
 | 
			
		||||
                            if state == Parse.EOL_COMMENT:
 | 
			
		||||
                                define_info['comment'] = ''
 | 
			
		||||
                            else:
 | 
			
		||||
                                define_info['comment'] = full_comment
 | 
			
		||||
                                comment_buff = []
 | 
			
		||||
 | 
			
		||||
                            # If the comment specifies units, add that to the info
 | 
			
		||||
                            units = re.match(r'^\(([^)]+)\)', full_comment)
 | 
			
		||||
                            if units:
 | 
			
		||||
                                units = units[1]
 | 
			
		||||
                                if units == 's' or units == 'sec': units = 'seconds'
 | 
			
		||||
                                define_info['units'] = units
 | 
			
		||||
 | 
			
		||||
                        # Set the options for the current #define
 | 
			
		||||
                        if define_name == "MOTHERBOARD" and boards != '':
 | 
			
		||||
                            define_info['options'] = boards
 | 
			
		||||
                        elif options_json != '':
 | 
			
		||||
                            define_info['options'] = options_json
 | 
			
		||||
                            if eol_options: options_json = ''
 | 
			
		||||
 | 
			
		||||
                        # Create section dict if it doesn't exist yet
 | 
			
		||||
                        if section not in sch_out[fk]: sch_out[fk][section] = {}
 | 
			
		||||
 | 
			
		||||
                        # If define has already been seen...
 | 
			
		||||
                        if define_name in sch_out[fk][section]:
 | 
			
		||||
                            info = sch_out[fk][section][define_name]
 | 
			
		||||
                            if isinstance(info, dict): info = [ info ]  # Convert a single dict into a list
 | 
			
		||||
                            info.append(define_info)                    # Add to the list
 | 
			
		||||
                        else:
 | 
			
		||||
                            # Add the define dict with name as key
 | 
			
		||||
                            sch_out[fk][section][define_name] = define_info
 | 
			
		||||
 | 
			
		||||
                        if state == Parse.EOL_COMMENT:
 | 
			
		||||
                            last_added_ref = define_info
 | 
			
		||||
 | 
			
		||||
    return sch_out
 | 
			
		||||
 | 
			
		||||
def dump_json(schema:dict, jpath:Path):
 | 
			
		||||
    with jpath.open('w') as jfile:
 | 
			
		||||
        json.dump(schema, jfile, ensure_ascii=False, indent=2)
 | 
			
		||||
 | 
			
		||||
def dump_yaml(schema:dict, ypath:Path):
 | 
			
		||||
    import yaml
 | 
			
		||||
    with ypath.open('w') as yfile:
 | 
			
		||||
        yaml.dump(schema, yfile, default_flow_style=False, width=120, indent=2)
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    try:
 | 
			
		||||
        schema = extract()
 | 
			
		||||
    except Exception as exc:
 | 
			
		||||
        print("Error: " + str(exc))
 | 
			
		||||
        schema = None
 | 
			
		||||
 | 
			
		||||
    if schema:
 | 
			
		||||
 | 
			
		||||
        # Get the first command line argument
 | 
			
		||||
        import sys
 | 
			
		||||
        if len(sys.argv) > 1:
 | 
			
		||||
            arg = sys.argv[1]
 | 
			
		||||
        else:
 | 
			
		||||
            arg = 'some'
 | 
			
		||||
 | 
			
		||||
        # JSON schema
 | 
			
		||||
        if arg in ['some', 'json', 'jsons']:
 | 
			
		||||
            print("Generating JSON ...")
 | 
			
		||||
            dump_json(schema, Path('schema.json'))
 | 
			
		||||
 | 
			
		||||
        # JSON schema (wildcard names)
 | 
			
		||||
        if arg in ['group', 'jsons']:
 | 
			
		||||
            group_options(schema)
 | 
			
		||||
            dump_json(schema, Path('schema_grouped.json'))
 | 
			
		||||
 | 
			
		||||
        # YAML
 | 
			
		||||
        if arg in ['some', 'yml', 'yaml']:
 | 
			
		||||
            try:
 | 
			
		||||
                import yaml
 | 
			
		||||
            except ImportError:
 | 
			
		||||
                print("Installing YAML module ...")
 | 
			
		||||
                import subprocess
 | 
			
		||||
                try:
 | 
			
		||||
                    subprocess.run(['python3', '-m', 'pip', 'install', 'pyyaml'])
 | 
			
		||||
                    import yaml
 | 
			
		||||
                except:
 | 
			
		||||
                    print("Failed to install YAML module")
 | 
			
		||||
                    return
 | 
			
		||||
 | 
			
		||||
            print("Generating YML ...")
 | 
			
		||||
            dump_yaml(schema, Path('schema.yml'))
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
							
								
								
									
										276
									
								
								buildroot/share/PlatformIO/scripts/signature.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										276
									
								
								buildroot/share/PlatformIO/scripts/signature.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,276 @@
 | 
			
		||||
#
 | 
			
		||||
# signature.py
 | 
			
		||||
#
 | 
			
		||||
import schema
 | 
			
		||||
 | 
			
		||||
import subprocess,re,json,hashlib
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Return all macro names in a header as an array, so we can take
 | 
			
		||||
# the intersection with the preprocessor output, giving a decent
 | 
			
		||||
# reflection of all enabled options that (probably) came from the
 | 
			
		||||
# configuration files. We end up with the actual configured state,
 | 
			
		||||
# better than what the config files say. You can then use the
 | 
			
		||||
# resulting config.ini to produce more exact configuration files.
 | 
			
		||||
#
 | 
			
		||||
def extract_defines(filepath):
 | 
			
		||||
    f = open(filepath, encoding="utf8").read().split("\n")
 | 
			
		||||
    a = []
 | 
			
		||||
    for line in f:
 | 
			
		||||
        sline = line.strip()
 | 
			
		||||
        if sline[:7] == "#define":
 | 
			
		||||
            # Extract the key here (we don't care about the value)
 | 
			
		||||
            kv = sline[8:].strip().split()
 | 
			
		||||
            a.append(kv[0])
 | 
			
		||||
    return a
 | 
			
		||||
 | 
			
		||||
# Compute the SHA256 hash of a file
 | 
			
		||||
def get_file_sha256sum(filepath):
 | 
			
		||||
    sha256_hash = hashlib.sha256()
 | 
			
		||||
    with open(filepath,"rb") as f:
 | 
			
		||||
        # Read and update hash string value in blocks of 4K
 | 
			
		||||
        for byte_block in iter(lambda: f.read(4096),b""):
 | 
			
		||||
            sha256_hash.update(byte_block)
 | 
			
		||||
    return sha256_hash.hexdigest()
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Compress a JSON file into a zip file
 | 
			
		||||
#
 | 
			
		||||
import zipfile
 | 
			
		||||
def compress_file(filepath, outpath):
 | 
			
		||||
    with zipfile.ZipFile(outpath, 'w', compression=zipfile.ZIP_BZIP2, compresslevel=9) as zipf:
 | 
			
		||||
        zipf.write(filepath, compress_type=zipfile.ZIP_BZIP2, compresslevel=9)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Compute the build signature. The idea is to extract all defines in the configuration headers
 | 
			
		||||
# to build a unique reversible signature from this build so it can be included in the binary
 | 
			
		||||
# We can reverse the signature to get a 1:1 equivalent configuration file
 | 
			
		||||
#
 | 
			
		||||
def compute_build_signature(env):
 | 
			
		||||
    if 'BUILD_SIGNATURE' in env:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    # Definitions from these files will be kept
 | 
			
		||||
    files_to_keep = [ 'Marlin/Configuration.h', 'Marlin/Configuration_adv.h' ]
 | 
			
		||||
 | 
			
		||||
    build_path = Path(env['PROJECT_BUILD_DIR'], env['PIOENV'])
 | 
			
		||||
 | 
			
		||||
    # Check if we can skip processing
 | 
			
		||||
    hashes = ''
 | 
			
		||||
    for header in files_to_keep:
 | 
			
		||||
        hashes += get_file_sha256sum(header)[0:10]
 | 
			
		||||
 | 
			
		||||
    marlin_json = build_path / 'marlin_config.json'
 | 
			
		||||
    marlin_zip = build_path / 'mc.zip'
 | 
			
		||||
 | 
			
		||||
    # Read existing config file
 | 
			
		||||
    try:
 | 
			
		||||
        with marlin_json.open() as infile:
 | 
			
		||||
            conf = json.load(infile)
 | 
			
		||||
            if conf['__INITIAL_HASH'] == hashes:
 | 
			
		||||
                # Same configuration, skip recomputing the building signature
 | 
			
		||||
                compress_file(marlin_json, marlin_zip)
 | 
			
		||||
                return
 | 
			
		||||
    except:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    # Get enabled config options based on preprocessor
 | 
			
		||||
    from preprocessor import run_preprocessor
 | 
			
		||||
    complete_cfg = run_preprocessor(env)
 | 
			
		||||
 | 
			
		||||
    # Dumb #define extraction from the configuration files
 | 
			
		||||
    conf_defines = {}
 | 
			
		||||
    all_defines = []
 | 
			
		||||
    for header in files_to_keep:
 | 
			
		||||
        defines = extract_defines(header)
 | 
			
		||||
        # To filter only the define we want
 | 
			
		||||
        all_defines += defines
 | 
			
		||||
        # To remember from which file it cames from
 | 
			
		||||
        conf_defines[header.split('/')[-1]] = defines
 | 
			
		||||
 | 
			
		||||
    r = re.compile(r"\(+(\s*-*\s*_.*)\)+")
 | 
			
		||||
 | 
			
		||||
    # First step is to collect all valid macros
 | 
			
		||||
    defines = {}
 | 
			
		||||
    for line in complete_cfg:
 | 
			
		||||
 | 
			
		||||
        # Split the define from the value
 | 
			
		||||
        key_val = line[8:].strip().decode().split(' ')
 | 
			
		||||
        key, value = key_val[0], ' '.join(key_val[1:])
 | 
			
		||||
 | 
			
		||||
        # Ignore values starting with two underscore, since it's low level
 | 
			
		||||
        if len(key) > 2 and key[0:2] == "__" :
 | 
			
		||||
            continue
 | 
			
		||||
        # Ignore values containing a parenthesis (likely a function macro)
 | 
			
		||||
        if '(' in key and ')' in key:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        # Then filter dumb values
 | 
			
		||||
        if r.match(value):
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        defines[key] = value if len(value) else ""
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Continue to gather data for CONFIGURATION_EMBEDDING or CONFIG_EXPORT
 | 
			
		||||
    #
 | 
			
		||||
    if not ('CONFIGURATION_EMBEDDING' in defines or 'CONFIG_EXPORT' in defines):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    # Second step is to filter useless macro
 | 
			
		||||
    resolved_defines = {}
 | 
			
		||||
    for key in defines:
 | 
			
		||||
        # Remove all boards now
 | 
			
		||||
        if key.startswith("BOARD_") and key != "BOARD_INFO_NAME":
 | 
			
		||||
            continue
 | 
			
		||||
        # Remove all keys ending by "_NAME" as it does not make a difference to the configuration
 | 
			
		||||
        if key.endswith("_NAME") and key != "CUSTOM_MACHINE_NAME":
 | 
			
		||||
            continue
 | 
			
		||||
        # Remove all keys ending by "_T_DECLARED" as it's a copy of extraneous system stuff
 | 
			
		||||
        if key.endswith("_T_DECLARED"):
 | 
			
		||||
            continue
 | 
			
		||||
        # Remove keys that are not in the #define list in the Configuration list
 | 
			
		||||
        if key not in all_defines + [ 'DETAILED_BUILD_VERSION', 'STRING_DISTRIBUTION_DATE' ]:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        # Don't be that smart guy here
 | 
			
		||||
        resolved_defines[key] = defines[key]
 | 
			
		||||
 | 
			
		||||
    # Generate a build signature now
 | 
			
		||||
    # We are making an object that's a bit more complex than a basic dictionary here
 | 
			
		||||
    data = {}
 | 
			
		||||
    data['__INITIAL_HASH'] = hashes
 | 
			
		||||
    # First create a key for each header here
 | 
			
		||||
    for header in conf_defines:
 | 
			
		||||
        data[header] = {}
 | 
			
		||||
 | 
			
		||||
    # Then populate the object where each key is going to (that's a O(N^2) algorithm here...)
 | 
			
		||||
    for key in resolved_defines:
 | 
			
		||||
        for header in conf_defines:
 | 
			
		||||
            if key in conf_defines[header]:
 | 
			
		||||
                data[header][key] = resolved_defines[key]
 | 
			
		||||
 | 
			
		||||
    # Every python needs this toy
 | 
			
		||||
    def tryint(key):
 | 
			
		||||
        try:
 | 
			
		||||
            return int(defines[key])
 | 
			
		||||
        except:
 | 
			
		||||
            return 0
 | 
			
		||||
 | 
			
		||||
    config_dump = tryint('CONFIG_EXPORT')
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Produce an INI file if CONFIG_EXPORT == 2
 | 
			
		||||
    #
 | 
			
		||||
    if config_dump == 2:
 | 
			
		||||
        print("Generating config.ini ...")
 | 
			
		||||
        config_ini = build_path / 'config.ini'
 | 
			
		||||
        with config_ini.open('w') as outfile:
 | 
			
		||||
            ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_EXPORT')
 | 
			
		||||
            filegrp = { 'Configuration.h':'config:basic', 'Configuration_adv.h':'config:advanced' }
 | 
			
		||||
            vers = defines["CONFIGURATION_H_VERSION"]
 | 
			
		||||
            dt_string = datetime.now().strftime("%Y-%m-%d at %H:%M:%S")
 | 
			
		||||
            ini_fmt = '{0:40}{1}\n'
 | 
			
		||||
            outfile.write(
 | 
			
		||||
                '#\n'
 | 
			
		||||
                + '# Marlin Firmware\n'
 | 
			
		||||
                + '# config.ini - Options to apply before the build\n'
 | 
			
		||||
                + '#\n'
 | 
			
		||||
                + f'# Generated by Marlin build on {dt_string}\n'
 | 
			
		||||
                + '#\n'
 | 
			
		||||
                + '\n'
 | 
			
		||||
                + '[config:base]\n'
 | 
			
		||||
                + ini_fmt.format('ini_use_config', ' = all')
 | 
			
		||||
                + ini_fmt.format('ini_config_vers', f' = {vers}')
 | 
			
		||||
            )
 | 
			
		||||
            # Loop through the data array of arrays
 | 
			
		||||
            for header in data:
 | 
			
		||||
                if header.startswith('__'):
 | 
			
		||||
                    continue
 | 
			
		||||
                outfile.write('\n[' + filegrp[header] + ']\n')
 | 
			
		||||
                for key in sorted(data[header]):
 | 
			
		||||
                    if key not in ignore:
 | 
			
		||||
                        val = 'on' if data[header][key] == '' else data[header][key]
 | 
			
		||||
                        outfile.write(ini_fmt.format(key.lower(), ' = ' + val))
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Produce a schema.json file if CONFIG_EXPORT == 3
 | 
			
		||||
    #
 | 
			
		||||
    if config_dump >= 3:
 | 
			
		||||
        try:
 | 
			
		||||
            conf_schema = schema.extract()
 | 
			
		||||
        except Exception as exc:
 | 
			
		||||
            print("Error: " + str(exc))
 | 
			
		||||
            conf_schema = None
 | 
			
		||||
 | 
			
		||||
        if conf_schema:
 | 
			
		||||
            #
 | 
			
		||||
            # Produce a schema.json file if CONFIG_EXPORT == 3
 | 
			
		||||
            #
 | 
			
		||||
            if config_dump in (3, 13):
 | 
			
		||||
                print("Generating schema.json ...")
 | 
			
		||||
                schema.dump_json(conf_schema, build_path / 'schema.json')
 | 
			
		||||
                if config_dump == 13:
 | 
			
		||||
                    schema.group_options(conf_schema)
 | 
			
		||||
                    schema.dump_json(conf_schema, build_path / 'schema_grouped.json')
 | 
			
		||||
 | 
			
		||||
            #
 | 
			
		||||
            # Produce a schema.yml file if CONFIG_EXPORT == 4
 | 
			
		||||
            #
 | 
			
		||||
            elif config_dump == 4:
 | 
			
		||||
                print("Generating schema.yml ...")
 | 
			
		||||
                try:
 | 
			
		||||
                    import yaml
 | 
			
		||||
                except ImportError:
 | 
			
		||||
                    env.Execute(env.VerboseAction(
 | 
			
		||||
                        '$PYTHONEXE -m pip install "pyyaml"',
 | 
			
		||||
                        "Installing YAML for schema.yml export",
 | 
			
		||||
                    ))
 | 
			
		||||
                    import yaml
 | 
			
		||||
                schema.dump_yaml(conf_schema, build_path / 'schema.yml')
 | 
			
		||||
 | 
			
		||||
    # Append the source code version and date
 | 
			
		||||
    data['VERSION'] = {}
 | 
			
		||||
    data['VERSION']['DETAILED_BUILD_VERSION'] = resolved_defines['DETAILED_BUILD_VERSION']
 | 
			
		||||
    data['VERSION']['STRING_DISTRIBUTION_DATE'] = resolved_defines['STRING_DISTRIBUTION_DATE']
 | 
			
		||||
    try:
 | 
			
		||||
        curver = subprocess.check_output(["git", "describe", "--match=NeVeRmAtCh", "--always"]).strip()
 | 
			
		||||
        data['VERSION']['GIT_REF'] = curver.decode()
 | 
			
		||||
    except:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Produce a JSON file for CONFIGURATION_EMBEDDING or CONFIG_EXPORT == 1
 | 
			
		||||
    #
 | 
			
		||||
    if config_dump == 1 or 'CONFIGURATION_EMBEDDING' in defines:
 | 
			
		||||
        with marlin_json.open('w') as outfile:
 | 
			
		||||
            json.dump(data, outfile, separators=(',', ':'))
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # The rest only applies to CONFIGURATION_EMBEDDING
 | 
			
		||||
    #
 | 
			
		||||
    if not 'CONFIGURATION_EMBEDDING' in defines:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    # Compress the JSON file as much as we can
 | 
			
		||||
    compress_file(marlin_json, marlin_zip)
 | 
			
		||||
 | 
			
		||||
    # Generate a C source file for storing this array
 | 
			
		||||
    with open('Marlin/src/mczip.h','wb') as result_file:
 | 
			
		||||
        result_file.write(
 | 
			
		||||
              b'#ifndef NO_CONFIGURATION_EMBEDDING_WARNING\n'
 | 
			
		||||
            + b'  #warning "Generated file \'mc.zip\' is embedded (Define NO_CONFIGURATION_EMBEDDING_WARNING to suppress this warning.)"\n'
 | 
			
		||||
            + b'#endif\n'
 | 
			
		||||
            + b'const unsigned char mc_zip[] PROGMEM = {\n '
 | 
			
		||||
        )
 | 
			
		||||
        count = 0
 | 
			
		||||
        for b in (build_path / 'mc.zip').open('rb').read():
 | 
			
		||||
            result_file.write(b' 0x%02X,' % b)
 | 
			
		||||
            count += 1
 | 
			
		||||
            if count % 16 == 0:
 | 
			
		||||
                result_file.write(b'\n ')
 | 
			
		||||
        if count % 16:
 | 
			
		||||
            result_file.write(b'\n')
 | 
			
		||||
        result_file.write(b'};\n')
 | 
			
		||||
							
								
								
									
										53
									
								
								buildroot/share/PlatformIO/scripts/simulator.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								buildroot/share/PlatformIO/scripts/simulator.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
#
 | 
			
		||||
# simulator.py
 | 
			
		||||
# PlatformIO pre: script for simulator builds
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
import pioutil
 | 
			
		||||
if pioutil.is_pio_build():
 | 
			
		||||
    # Get the environment thus far for the build
 | 
			
		||||
    Import("env")
 | 
			
		||||
 | 
			
		||||
    #print(env.Dump())
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Give the binary a distinctive name
 | 
			
		||||
    #
 | 
			
		||||
 | 
			
		||||
    env['PROGNAME'] = "MarlinSimulator"
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # If Xcode is installed add the path to its Frameworks folder,
 | 
			
		||||
    # or if Mesa is installed try to use its GL/gl.h.
 | 
			
		||||
    #
 | 
			
		||||
 | 
			
		||||
    import sys
 | 
			
		||||
    if sys.platform == 'darwin':
 | 
			
		||||
 | 
			
		||||
        #
 | 
			
		||||
        # Silence half of the ranlib warnings. (No equivalent for 'ARFLAGS')
 | 
			
		||||
        #
 | 
			
		||||
        env['RANLIBFLAGS'] += [ "-no_warning_for_no_symbols" ]
 | 
			
		||||
 | 
			
		||||
        # Default paths for Xcode and a lucky GL/gl.h dropped by Mesa
 | 
			
		||||
        xcode_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks"
 | 
			
		||||
        mesa_path = "/opt/local/include/GL/gl.h"
 | 
			
		||||
 | 
			
		||||
        import os.path
 | 
			
		||||
 | 
			
		||||
        if os.path.exists(xcode_path):
 | 
			
		||||
 | 
			
		||||
            env['BUILD_FLAGS'] += [ "-F" + xcode_path ]
 | 
			
		||||
            print("Using OpenGL framework headers from Xcode.app")
 | 
			
		||||
 | 
			
		||||
        elif os.path.exists(mesa_path):
 | 
			
		||||
 | 
			
		||||
            env['BUILD_FLAGS'] += [ '-D__MESA__' ]
 | 
			
		||||
            print("Using OpenGL header from", mesa_path)
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
 | 
			
		||||
            print("\n\nNo OpenGL headers found. Install Xcode for matching headers, or use 'sudo port install mesa' to get a GL/gl.h.\n\n")
 | 
			
		||||
 | 
			
		||||
            # Break out of the PIO build immediately
 | 
			
		||||
            sys.exit(1)
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
import os,sys,shutil
 | 
			
		||||
Import("env")
 | 
			
		||||
 | 
			
		||||
from SCons.Script import DefaultEnvironment
 | 
			
		||||
board = DefaultEnvironment().BoardConfig()
 | 
			
		||||
 | 
			
		||||
def noencrypt(source, target, env):
 | 
			
		||||
  firmware = os.path.join(target[0].dir.path, board.get("build.firmware"))
 | 
			
		||||
  # do not overwrite encrypted firmware if present
 | 
			
		||||
  if not os.path.isfile(firmware):
 | 
			
		||||
    shutil.copy(target[0].path, firmware)
 | 
			
		||||
 | 
			
		||||
if 'offset' in board.get("build").keys():
 | 
			
		||||
  LD_FLASH_OFFSET = board.get("build.offset")
 | 
			
		||||
 | 
			
		||||
  for define in env['CPPDEFINES']:
 | 
			
		||||
    if define[0] == "VECT_TAB_OFFSET":
 | 
			
		||||
      env['CPPDEFINES'].remove(define)
 | 
			
		||||
  env['CPPDEFINES'].append(("VECT_TAB_OFFSET", LD_FLASH_OFFSET))
 | 
			
		||||
 | 
			
		||||
  maximum_ram_size = board.get("upload.maximum_ram_size")
 | 
			
		||||
 | 
			
		||||
  for i, flag in enumerate(env["LINKFLAGS"]):
 | 
			
		||||
    if "-Wl,--defsym=LD_FLASH_OFFSET" in flag:
 | 
			
		||||
      env["LINKFLAGS"][i] = "-Wl,--defsym=LD_FLASH_OFFSET=" + LD_FLASH_OFFSET
 | 
			
		||||
    if "-Wl,--defsym=LD_MAX_DATA_SIZE" in flag:
 | 
			
		||||
      env["LINKFLAGS"][i] = "-Wl,--defsym=LD_MAX_DATA_SIZE=" + str(maximum_ram_size - 40)
 | 
			
		||||
 | 
			
		||||
  if 'firmware' in board.get("build").keys():
 | 
			
		||||
    env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", noencrypt);
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user