diff --git a/README.md b/README.md index bcaf6d2bc..f9a252316 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Arduino_Tools [![GitHub release](https://img.shields.io/github/release/stm32duino/Arduino_Tools.svg)](https://github.com/stm32duino/Arduino_Tools/releases/latest) -[![GitHub commits](https://img.shields.io/github/commits-since/stm32duino/Arduino_Tools/2.2.2.svg)](https://github.com/stm32duino/Arduino_Tools/compare/2.2.2...master) +[![GitHub commits](https://img.shields.io/github/commits-since/stm32duino/Arduino_Tools/2.3.0.svg)](https://github.com/stm32duino/Arduino_Tools/compare/2.3.0...master) Contains upload tools for STM32 based boards and some other usefull scripts. diff --git a/linux/massStorageCopy.sh b/linux/massStorageCopy.sh index 237befa8b..3528c2203 100755 --- a/linux/massStorageCopy.sh +++ b/linux/massStorageCopy.sh @@ -20,12 +20,11 @@ usage() { echo "## Note:" echo "## -I and -O are optionals and kept for backward compatibility." echo "############################################################" - exit 0 + exit "$1" } if [ $# -lt 2 ]; then - usage - exit 1 + usage 1 fi # Parsing options diff --git a/macosx/dfu-prefix b/macosx/dfu-prefix index fdd267114..6bc5f3286 100755 Binary files a/macosx/dfu-prefix and b/macosx/dfu-prefix differ diff --git a/macosx/dfu-suffix b/macosx/dfu-suffix index 6d17d7e5e..73eb3895f 100755 Binary files a/macosx/dfu-suffix and b/macosx/dfu-suffix differ diff --git a/macosx/dfu-util b/macosx/dfu-util index 895bb2378..b6df5525b 100755 Binary files a/macosx/dfu-util and b/macosx/dfu-util differ diff --git a/macosx/hid-flash b/macosx/hid-flash index 8acc45772..ce32e672c 100755 Binary files a/macosx/hid-flash and b/macosx/hid-flash differ diff --git a/macosx/libusb-1.0.0.dylib b/macosx/libusb-1.0.0.dylib new file mode 100644 index 000000000..352f17fd7 Binary files /dev/null and b/macosx/libusb-1.0.0.dylib differ diff --git a/macosx/massStorageCopy.sh b/macosx/massStorageCopy.sh index 0f176d15b..3b58ebf9f 100755 --- a/macosx/massStorageCopy.sh +++ b/macosx/massStorageCopy.sh @@ -20,12 +20,11 @@ usage() { echo "## Note:" echo "## -I and -O are optionals and kept for backward compatibility." echo "############################################################" - exit 0 + exit "$1" } if [ $# -lt 2 ]; then - usage - exit 1 + usage 1 fi # Parsing options diff --git a/macosx/upload_reset b/macosx/upload_reset index 29290310b..41cbb61d2 100755 Binary files a/macosx/upload_reset and b/macosx/upload_reset differ diff --git a/src/build_mac.sh b/src/build_mac.sh new file mode 100755 index 000000000..07785bb8a --- /dev/null +++ b/src/build_mac.sh @@ -0,0 +1,172 @@ +#!/bin/sh + +set -eu + +[ -z "${ARCH+x}" ] && ARCH=universal + +case "${ARCH}" in + arm64) + # Build for arm64, either as a same-architecture or cross-architecture + # build. + CONFIGURE_HOST_ARG="--host=aarch64-apple-darwin" + CC_ARCH_ARG="-arch ${ARCH}" + + # Don't collide with macosx, which has traditionally been used for x86_64 + # code. + ARCH_DIR=mac-arm64 + ;; + universal) + # Build for x86_64 and arm64 simultaneously, putting the results into + # "universal" or "fat" binaries. + CONFIGURE_HOST_ARG= + CC_ARCH_ARG="-arch x86_64 -arch arm64" + + # It's fine to put universal code into macosx, traditionally used for x86_64 + # code, because it will contain x86_64 code and will run without trouble on + # x86_64 systems. Using the same directory for universal files means that + # these tools will remain at a stable path across a transition between + # x86_64 and arm64. + ARCH_DIR=macosx + ;; + x86_64) + # Build for x86_64, either as a same-architecture or cross-architecture + # build. + CONFIGURE_HOST_ARG="--host=${ARCH}-apple-darwin" + CC_ARCH_ARG="-arch ${ARCH}" + + ARCH_DIR=macosx + ;; + *) + # Build for some other ${ARCH}, either as a same-architecture or + # cross-architecture build. + CONFIGURE_HOST_ARG="--host=${ARCH}-apple-darwin" + CC_ARCH_ARG="-arch ${ARCH}" + + ARCH_DIR="mac-${ARCH}" + ;; +esac + +if [ -z "${MIN_OS_VERSION+x}" ]; then + case "${ARCH}" in + arm64) + # macOS 11 was the first to support arm64. + MIN_OS_VERSION=11.0 + ;; + universal | x86_64) + # Although this could be set lower, the xPack tools declare support for + # macOS 10.13, so it's unlikely that anyone would be using anything older. + # + # In a universal build, the toolchain will use this value for the x86_64 + # build, but will automatically increase the minimum to 11.0 for the arm64 + # build, because that was the first OS version to support arm64. + MIN_OS_VERSION=10.13 + ;; + esac +fi +if [ -n "${MIN_OS_VERSION+x}" ]; then + CC_MIN_OS_VERSION_ARG="-mmacosx-version-min=${MIN_OS_VERSION}" +fi + +MAKE_J_ARG="-j$(sysctl -n hw.ncpu)" +BASE_CFLAGS="-Os -flto" +BASE_LDFLAGS="-dead_strip" + +LIBUSB_VERSION=1.0.27 +DFU_UTIL_VERSION=0.11 +STM32_HID_BOOTLOADER_VERSION=2.2.2 + +set -x + +cd "$(dirname "${0}")/.." + +( + cd .. + + # dfu-util depends on libusb, which isn't part of the operating system. + # Provide a build of libusb to satisfy that dependency. + [ ! -d libusb ] && git clone https://github.com/libusb/libusb.git + cd libusb + git checkout "v${LIBUSB_VERSION}" + # git clean -fdx + # git checkout -- . + sh bootstrap.sh + CC="clang ${CC_ARCH_ARG} ${CC_MIN_OS_VERSION_ARG}" \ + CFLAGS="${BASE_CFLAGS}" \ + LDFLAGS="${BASE_LDFLAGS} -Wl,-source_version,${LIBUSB_VERSION}" \ + sh configure ${CONFIGURE_HOST_ARG} + make clean + make ${MAKE_J_ARG} + + # Rewrite the LC_ID_DYLIB in libusb-1.0.0.dylib so that other modules that + # link against it will expect to find it in the same directory that they are + # located in (@loader_path). Later, libusb-1.0.0.dylib will be copied to the + # same directory as dfu-util and the other executables that rely on it. + install_name_tool \ + -id @loader_path/libusb-1.0.0.dylib \ + libusb/.libs/libusb-1.0.0.dylib + + cd .. + + [ ! -d dfu-util ] && git clone git://git.code.sf.net/p/dfu-util/dfu-util + cd dfu-util + git checkout "v${DFU_UTIL_VERSION}" + # git clean -fdx + # git checkout -- . + sh autogen.sh + CC="clang ${CC_ARCH_ARG} ${CC_MIN_OS_VERSION_ARG}" \ + CFLAGS="${BASE_CFLAGS} -fvisibility=hidden" \ + LDFLAGS="${BASE_LDFLAGS} -Wl,-source_version,${DFU_UTIL_VERSION}" \ + USB_CFLAGS="-I$(pwd)/../libusb/libusb" \ + USB_LIBS="-L$(pwd)/../libusb/libusb/.libs -lusb-1.0.0" \ + sh configure ${CONFIGURE_HOST_ARG} + make clean + make ${MAKE_J_ARG} + cd .. + + [ ! -d STM32_HID_Bootloader ] && + git clone https://github.com/Serasidis/STM32_HID_Bootloader.git + cd STM32_HID_Bootloader + git checkout "${STM32_HID_BOOTLOADER_VERSION}" + # git clean -fdx + # git checkout -- . + git checkout -- cli/main.c + + # Isolate and apply the patch from + # https://github.com/Serasidis/STM32_HID_Bootloader/issues/68#issuecomment-2009105851 + curl --silent \ + https://api.github.com/repos/Serasidis/STM32_HID_Bootloader/issues/comments/2009105851 | + jq --raw-output .body | + sed -e 's/\r//g' -e '1,/^```/d' -e '/^```$/,$d' | + patch cli/main.c + + make -C cli clean + make -C cli ${MAKE_J_ARG} \ + CC="clang ${CC_ARCH_ARG} ${CC_MIN_OS_VERSION_ARG}" \ + CFLAGS="${BASE_CFLAGS} -fvisibility=hidden -Wall -Werror -c" \ + LDFLAGS="${BASE_LDFLAGS} -Wl,-source_version,${STM32_HID_BOOTLOADER_VERSION}" + cd .. +) + +mkdir -p "${ARCH_DIR}" + +cp ../libusb/libusb/.libs/libusb-1.0.0.dylib \ + ../dfu-util/src/dfu-prefix \ + ../dfu-util/src/dfu-suffix \ + ../dfu-util/src/dfu-util \ + ../STM32_HID_Bootloader/cli/hid-flash \ + "${ARCH_DIR}/" +chmod -x "${ARCH_DIR}/libusb-1.0.0.dylib" + +# It would be nice to include -Wl,-source_version here, but that's tricky to do +# for code that's in this repository, and probably won't be tagged with a +# version until after this tool is built. +clang \ + ${CC_ARCH_ARG} \ + ${CC_MIN_OS_VERSION_ARG} \ + ${BASE_CFLAGS} \ + -fvisibility=hidden \ + ${BASE_LDFLAGS} \ + -Wall \ + -Werror \ + -o "${ARCH_DIR}/upload_reset" \ + src/upload_reset/unix/upload_reset.c diff --git a/stm32CubeProg.sh b/stm32CubeProg.sh index 403d1a425..5cba7d839 100644 --- a/stm32CubeProg.sh +++ b/stm32CubeProg.sh @@ -2,6 +2,8 @@ set -o nounset # Treat unset variables as an error # set -o xtrace # Print command traces before executing command. +UNAME_OS="$(uname -s)" +GNU_GETOPT= STM32CP_CLI= INTERFACE= PORT= @@ -23,7 +25,7 @@ usage() { echo "Usage: $(basename "$0") [OPTIONS]... Mandatory options: - -i, --interface <'swd'/'dfu'/'serial'> interface identifier: 'swd', 'dfu' or 'serial' + -i, --interface <'swd'/'dfu'/'serial'/'jlink'> interface identifier: 'swd', 'dfu', 'serial' or 'jlink' -f, --file file path to be downloaded: bin or hex Optional options: -e, --erase erase all sectors before flashing @@ -53,11 +55,73 @@ aborting() { exit 1 } +# Check STM32CubeProgrammer cli availability and getopt version +case "${UNAME_OS}" in + Linux*) + STM32CP_CLI=STM32_Programmer.sh + if ! command -v $STM32CP_CLI >/dev/null 2>&1; then + export PATH="$HOME/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin":"$PATH" + fi + if ! command -v $STM32CP_CLI >/dev/null 2>&1; then + export PATH="/opt/stm32cubeprog/bin":"$PATH" + fi + if ! command -v $STM32CP_CLI >/dev/null 2>&1; then + aborting + fi + ;; + Darwin*) + STM32CP_CLI=STM32_Programmer_CLI + if ! command -v $STM32CP_CLI >/dev/null 2>&1; then + export PATH="/Applications/STMicroelectronics/STM32Cube/STM32CubeProgrammer/STM32CubeProgrammer.app/Contents/MacOs/bin":"$PATH" + fi + if ! command -v $STM32CP_CLI >/dev/null 2>&1; then + aborting + fi + if ! command -v /usr/local/opt/gnu-getopt/bin/getopt >/dev/null 2>&1; then + if ! command -v /opt/homebrew/opt/gnu-getopt/bin/getopt >/dev/null 2>&1; then + echo "Warning: long options not supported due to getopt from FreeBSD usage." + GNU_GETOPT=n + else + export PATH="/opt/homebrew/opt/gnu-getopt/bin":"$PATH" + fi + else + export PATH="/usr/local/opt/gnu-getopt/bin":"$PATH" + fi + ;; + Windows*) + STM32CP_CLI=STM32_Programmer_CLI.exe + if ! command -v $STM32CP_CLI >/dev/null 2>&1; then + if [ -n "${PROGRAMFILES+x}" ]; then + STM32CP86=${PROGRAMFILES}/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin + export PATH="${STM32CP86}":"$PATH" + fi + if [ -n "${PROGRAMW6432+x}" ]; then + STM32CP=${PROGRAMW6432}/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin + export PATH="${STM32CP}":"$PATH" + fi + if ! command -v $STM32CP_CLI >/dev/null 2>&1; then + aborting + fi + fi + ;; + *) + echo "Unknown host OS: ${UNAME_OS}." >&2 + exit 1 + ;; +esac + # parse command line arguments # options may be followed by one colon to indicate they have a required arg -if ! options=$(getopt -a -o hi:ef:o:c:r:d:v:p: --long help,interface:,erase,file:,offset:,com:,rts:,dtr:,vid:,pid: -- "$@"); then - echo "Terminating..." >&2 - exit 1 +if [ -n "${GNU_GETOPT}" ]; then + if ! options=$(getopt hi:ef:o:c:r:d:v:p: "$@"); then + echo "Terminating..." >&2 + exit 1 + fi +else + if ! options=$(getopt -a -o hi:ef:o:c:r:d:v:p: --long help,interface:,erase,file:,offset:,com:,rts:,dtr:,vid:,pid: -- "$@"); then + echo "Terminating..." >&2 + exit 1 + fi fi eval set -- "$options" @@ -109,53 +173,12 @@ while true; do shift break ;; + *) + echo "Unknown option $1" + usage 1 + ;; esac done -# Check STM32CubeProgrammer cli availability, fallback to dfu-util if protocol dfu -UNAME_OS="$(uname -s)" -case "${UNAME_OS}" in - Linux*) - STM32CP_CLI=STM32_Programmer.sh - if ! command -v $STM32CP_CLI >/dev/null 2>&1; then - export PATH="$HOME/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin":"$PATH" - fi - if ! command -v $STM32CP_CLI >/dev/null 2>&1; then - export PATH="/opt/stm32cubeprog/bin":"$PATH" - fi - if ! command -v $STM32CP_CLI >/dev/null 2>&1; then - aborting - fi - ;; - Darwin*) - STM32CP_CLI=STM32_Programmer_CLI - if ! command -v $STM32CP_CLI >/dev/null 2>&1; then - export PATH="/Applications/STMicroelectronics/STM32Cube/STM32CubeProgrammer/STM32CubeProgrammer.app/Contents/MacOs/bin":"$PATH" - fi - if ! command -v $STM32CP_CLI >/dev/null 2>&1; then - aborting - fi - ;; - Windows*) - STM32CP_CLI=STM32_Programmer_CLI.exe - if ! command -v $STM32CP_CLI >/dev/null 2>&1; then - if [ -n "${PROGRAMFILES+x}" ]; then - STM32CP86=${PROGRAMFILES}/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin - export PATH="${STM32CP86}":"$PATH" - fi - if [ -n "${PROGRAMW6432+x}" ]; then - STM32CP=${PROGRAMW6432}/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin - export PATH="${STM32CP}":"$PATH" - fi - if ! command -v $STM32CP_CLI >/dev/null 2>&1; then - aborting - fi - fi - ;; - *) - echo "Unknown host OS: ${UNAME_OS}." >&2 - exit 1 - ;; -esac # Check mandatory options if [ -z "${INTERFACE}" ]; then @@ -201,6 +224,9 @@ case "${INTERFACE}" in fi ${STM32CP_CLI} --connect port="${PORT}" "${RTS}" "${DTR}" "${ERASE}" --quietMode --download "${FILEPATH}" "${ADDRESS}" --start "${ADDRESS}" ;; + jlink) + ${STM32CP_CLI} --connect port=JLINK ap=0 "${ERASE}" --quietMode --download "${FILEPATH}" "${ADDRESS}" --start "${ADDRESS}" + ;; *) echo "Protocol unknown!" >&2 usage 4