diff --git a/README.md b/README.md index 936507522..391dbc37b 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.4.0.svg)](https://github.com/stm32duino/Arduino_Tools/compare/2.4.0...main) +[![GitHub commits](https://img.shields.io/github/commits-since/stm32duino/Arduino_Tools/2.5.0.svg)](https://github.com/stm32duino/Arduino_Tools/compare/2.4.0...main) Contains upload tools for STM32 based boards and some other usefull scripts. diff --git a/stm32CubeProg.sh b/stm32CubeProg.sh index 065cb035f..1fd1f8bc4 100644 --- a/stm32CubeProg.sh +++ b/stm32CubeProg.sh @@ -3,7 +3,7 @@ set -o nounset # Treat unset variables as an error # set -o xtrace # Print command traces before executing command. UNAME_OS="$(uname -s)" -GNU_GETOPT= +GNU_GETOPT="n" # "y" if GNU getopt is available STM32CP_CLI= INTERFACE= PORT= @@ -12,8 +12,11 @@ OFFSET=0x0 # Optional ADDRESS=0x8000000 START=0x8000000 -MODE=UR ERASE= +# Optional for SWD +FREQ= +MODE=UR +SERIAL_NUMBER= # Optional for Serial RTS= DTR= @@ -29,23 +32,27 @@ usage() { Mandatory options: -i, --interface <'swd'/'dfu'/'serial'/'jlink'> interface identifier: 'swd', 'dfu', 'serial' or 'jlink' - -f, --file file path to be downloaded: bin or hex + -b, --bin binary file path to be downloaded: bin or hex Optional options: -a, --address flash base address. Default: $ADDRESS -e, --erase erase all sectors before flashing - -m, --mode connection mode: UR (default), HOTPLUG, POWERDOWN or hwRstPulse -s, --start start address after flashing. Default: $START -o, --offset offset from flash base ($ADDRESS) where flashing should start + Specific options for SWD protocol: + Optional: + -f, --freq SWD frequency in KHz. + -m, --mode connection mode: UR (default), HOTPLUG, POWERDOWN or hwRstPulse + -n, --snum serial number of the ST-Link device (if multiple ST-Link devices are connected) Specific options for Serial protocol: Mandatory: - -c, --com serial identifier, ex: COM1 or /dev/ttyS0,... + -c, --com serial identifier, ex: COM1 or /dev/ttyS0,... Optional: - -r, --rts polarity of RTS signal ('low' by default) -d, --dtr polarity of DTR signal - --parity parity bit configuration ('even' by default) + -p, --parity parity bit configuration ('even' by default) + -r, --rts polarity of RTS signal ('low' by default) - Specific options for DFU protocol: + Specific options for DFU protocol: Mandatory: -v, --vid vendor id, ex: 0x0483 -p, --pid product id, ex: 0xdf11 @@ -62,7 +69,71 @@ aborting() { exit 1 } -# Check STM32CubeProgrammer cli availability and getopt version +check_getopt() { + case "${UNAME_OS}" in + Linux* | Windows*) + GNU_GETOPT="y" + ;; + Darwin*) + # Check if getopt is in the path and if it is gnu or BSD version in the path + if command -v getopt >/dev/null 2>&1; then + getopt --test >/dev/null 2>&1 + if [ $? -eq 4 ]; then + GNU_GETOPT="y" + fi + fi + # If getopt is not gnu version, check if it is installed via brew + if [ "${GNU_GETOPT}" != "y" ]; then + if command -v brew >/dev/null 2>&1; then + BREW_PREFIX=$(brew --prefix) + if command -v "${BREW_PREFIX}/bin/getopt" >/dev/null 2>&1; then + "${BREW_PREFIX}"/bin/getopt --test >/dev/null 2>&1 + if [ $? -eq 4 ]; then + export PATH="${BREW_PREFIX}/bin:$PATH" + GNU_GETOPT="y" + fi + fi + if [ "${GNU_GETOPT}" != "y" ]; then + if command -v "${BREW_PREFIX}/opt/gnu-getopt/bin/getopt" >/dev/null 2>&1; then + export PATH="${BREW_PREFIX}/opt/gnu-getopt/bin":"$PATH" + GNU_GETOPT="y" + fi + fi + fi + # Check for MacPorts getopt + if [ "${GNU_GETOPT}" != "y" ]; then + if command -v /opt/local/bin/getopt >/dev/null 2>&1; then + /opt/local/bin/getopt --test >/dev/null 2>&1 + if [ $? -eq 4 ]; then + export PATH="/opt/local/bin:$PATH" + GNU_GETOPT="y" + fi + fi + fi + # Fallback to previous check + if [ "${GNU_GETOPT}" != "y" ]; then + 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 + export PATH="/opt/homebrew/opt/gnu-getopt/bin":"$PATH" + GNU_GETOPT="y" + fi + else + export PATH="/usr/local/opt/gnu-getopt/bin":"$PATH" + GNU_GETOPT="y" + fi + fi + fi + ;; + *) + echo "Unknown host OS: ${UNAME_OS}." >&2 + exit 1 + ;; + esac +} + +check_getopt + +# Check STM32CubeProgrammer cli availability case "${UNAME_OS}" in Linux*) STM32CP_CLI=STM32_Programmer.sh @@ -84,16 +155,6 @@ case "${UNAME_OS}" in 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 @@ -119,13 +180,15 @@ esac # parse command line arguments # options may be followed by one colon to indicate they have a required arg -if [ -n "${GNU_GETOPT}" ]; then - if ! options=$(getopt hi:ef:o:c:r:d:v:p: "$@"); then +if [ "${GNU_GETOPT}" = "y" ]; then + if ! options=$(getopt -a -o hi:b:a:es:o:f:m:n:c:d:p:r:v: --long help,interface:,bin:,address:,erase,start:,offset:,freq:,mode:,snum:,com:,dtr:,parity:,rts:,pid:,vid: -- "$@"); then echo "Terminating..." >&2 exit 1 fi else - if ! options=$(getopt -a -o a:hi:m:ef:o:c:r:s:d:v:p: --long address:,help,interface:,mode:,erase,file:,start:,offset:,com:,rts:,dtr:,vid:,pid:,parity: -- "$@"); then + echo "Warning: long options not supported due to getopt from FreeBSD usage." + echo " Space in arguments is not supported." + if ! options=$(getopt hi:b:a:es:o:f:m:n:c:d:p:r:v: "$@"); then echo "Terminating..." >&2 exit 1 fi @@ -143,52 +206,57 @@ while true; do echo "Selected interface: $INTERFACE" shift 2 ;; - -m | --mode) - MODE=$2 + -b | --bin) + FILEPATH=$2 shift 2 ;; -a | --address) ADDRESS=$2 shift 2 ;; - -s | --start) - START=$2 - shift 2 - ;; -e | --erase) ERASE="--erase all" shift 1 ;; - -f | --file) - FILEPATH=$2 + -s | --start) + START=$2 shift 2 ;; -o | --offset) OFFSET=$2 shift 2 ;; - -c | --com) - PORT=$2 + -f | --freq) + FREQ=$2 shift 2 ;; - -r | --rts) - RTS=$(echo "rts=$2" | tr '[:upper:]' '[:lower:]') + -m | --mode) + MODE=$2 + shift 2 + ;; + -n | --snum) + SERIAL_NUMBER="$2" + shift 2 + ;; + -c | --com) + PORT=$2 shift 2 ;; -d | --dtr) DTR=$(echo "dtr=$2" | tr '[:upper:]' '[:lower:]') shift 2 ;; - -v | --vid) - VID=$2 + -p | --pid | --parity) + PID=$2 + PARITY=$(echo "$2" | tr '[:lower:]' '[:upper:]') shift 2 ;; - -p | --pid) - PID=$2 + -r | --rts) + RTS=$(echo "rts=$2" | tr '[:upper:]' '[:lower:]') shift 2 ;; - --parity) - PARITY=$(echo "$2" | tr '[:lower:]' '[:upper:]') + -v | --vid) + VID=$2 shift 2 ;; --) @@ -210,7 +278,7 @@ if [ -z "${INTERFACE}" ]; then usage 1 fi if [ -z "${FILEPATH}" ]; then - echo "Error missing file argmument!" >&2 + echo "Error missing binary file argument!" >&2 usage 1 fi if [ ! -r "${FILEPATH}" ]; then @@ -220,7 +288,23 @@ fi case "${INTERFACE}" in swd) - ${STM32CP_CLI} --connect port=SWD mode="${MODE}" "${ERASE}" --quietMode --download "${FILEPATH}" "${ADDRESS}" --start "${START}" + PORT_PARAM="port=SWD" + if [ -n "${FREQ}" ]; then + case "${FREQ}" in + 0) ;; + *[!0-9]*) + echo "Invalid SWD frequency (expected integer KHz): ${FREQ}" >&2 + exit 1 + ;; + *) + PORT_PARAM="${PORT_PARAM} freq=${FREQ}" + ;; + esac + fi + if [ -n "${SERIAL_NUMBER}" ] && [ "${SERIAL_NUMBER}" != "0" ]; then + PORT_PARAM="${PORT_PARAM} sn=${SERIAL_NUMBER}" + fi + ${STM32CP_CLI} --connect "${PORT_PARAM}" mode="${MODE}" "${ERASE}" --quietMode --download "${FILEPATH}" "${ADDRESS}" --start "${START}" ;; dfu) if [ -z "${VID}" ] || [ -z "${PID}" ]; then