From 0fbba8cb1fdd557da52e6b1f5cc8d67da834b04e Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 21 Jul 2026 10:17:21 +0200 Subject: [PATCH 1/8] chore(stm32cubeprog): add short parity option Even if -p is also used for pid they are mutually exclusive. Signed-off-by: Frederic Pillon --- stm32CubeProg.sh | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/stm32CubeProg.sh b/stm32CubeProg.sh index 065cb035f..5e2431d2a 100644 --- a/stm32CubeProg.sh +++ b/stm32CubeProg.sh @@ -43,7 +43,7 @@ usage() { 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) Specific options for DFU protocol: Mandatory: @@ -183,11 +183,8 @@ while true; do VID=$2 shift 2 ;; - -p | --pid) + -p | --pid | --parity) PID=$2 - shift 2 - ;; - --parity) PARITY=$(echo "$2" | tr '[:lower:]' '[:upper:]') shift 2 ;; From c16ca3b3961f97bb8cda26564c8bfb445e08e35b Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 21 Jul 2026 11:37:16 +0200 Subject: [PATCH 2/8] fix(stm32cubeprog): missing short arguments for BSD getopt Signed-off-by: Frederic Pillon --- stm32CubeProg.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stm32CubeProg.sh b/stm32CubeProg.sh index 5e2431d2a..a3f9d24ab 100644 --- a/stm32CubeProg.sh +++ b/stm32CubeProg.sh @@ -120,7 +120,7 @@ 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 ! options=$(getopt a:hi:m:ef:o:c:r:s:d:v:p: "$@"); then echo "Terminating..." >&2 exit 1 fi From f3cf2b4bc8f2943b0565fdd21e471c7bbd9fad8d Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 21 Jul 2026 14:01:29 +0200 Subject: [PATCH 3/8] feat(stm32cubeprog): change -f/--file to -b/-bin Signed-off-by: Frederic Pillon --- stm32CubeProg.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stm32CubeProg.sh b/stm32CubeProg.sh index a3f9d24ab..25f822fb1 100644 --- a/stm32CubeProg.sh +++ b/stm32CubeProg.sh @@ -29,7 +29,7 @@ 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 @@ -120,12 +120,12 @@ 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 a:hi:m:ef:o:c:r:s:d:v:p: "$@"); then + if ! options=$(getopt a:b:hi:m:e:o:c:r:s:d:v:p: "$@"); 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 + if ! options=$(getopt -a -o a:b:hi:m:e:o:c:r:s:d:v:p: --long address:,bin:,help,interface:,mode:,erase,start:,offset:,com:,rts:,dtr:,vid:,pid:,parity: -- "$@"); then echo "Terminating..." >&2 exit 1 fi @@ -159,7 +159,7 @@ while true; do ERASE="--erase all" shift 1 ;; - -f | --file) + -b | --bin) FILEPATH=$2 shift 2 ;; @@ -207,7 +207,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 From ce48a420e04256b354b21a84ad59e2c91ba482a1 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 21 Jul 2026 14:37:22 +0200 Subject: [PATCH 4/8] chore(stm32cubeprog): review options sort per feature and alphabetical order. Signed-off-by: Frederic Pillon --- stm32CubeProg.sh | 50 ++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/stm32CubeProg.sh b/stm32CubeProg.sh index 25f822fb1..745b47fce 100644 --- a/stm32CubeProg.sh +++ b/stm32CubeProg.sh @@ -12,8 +12,9 @@ OFFSET=0x0 # Optional ADDRESS=0x8000000 START=0x8000000 -MODE=UR ERASE= +# Optional for SWD +MODE=UR # Optional for Serial RTS= DTR= @@ -33,19 +34,22 @@ usage() { 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: + -m, --mode connection mode: UR (default), HOTPLUG, POWERDOWN or hwRstPulse + 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 -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 @@ -120,12 +124,12 @@ 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 a:b:hi:m:e:o:c:r:s:d:v:p: "$@"); then + if ! options=$(getopt hi:b:a:es:o:m:c:d:p:r:v: "$@"); then echo "Terminating..." >&2 exit 1 fi else - if ! options=$(getopt -a -o a:b:hi:m:e:o:c:r:s:d:v:p: --long address:,bin:,help,interface:,mode:,erase,start:,offset:,com:,rts:,dtr:,vid:,pid:,parity: -- "$@"); then + if ! options=$(getopt -a -o hi:b:a:es:o:m:c:d:p:r:v: --long help,interface:,bin:,address:,erase,start:,offset:,mode:,com:,dtr:,parity:,rts:,pid:,vid: -- "$@"); then echo "Terminating..." >&2 exit 1 fi @@ -143,51 +147,51 @@ 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 ;; - -b | --bin) - FILEPATH=$2 + -s | --start) + START=$2 shift 2 ;; -o | --offset) OFFSET=$2 shift 2 ;; - -c | --com) - PORT=$2 + -m | --mode) + MODE=$2 shift 2 ;; - -r | --rts) - RTS=$(echo "rts=$2" | tr '[:upper:]' '[:lower:]') + -c | --com) + PORT=$2 shift 2 ;; -d | --dtr) DTR=$(echo "dtr=$2" | tr '[:upper:]' '[:lower:]') shift 2 ;; - -v | --vid) - VID=$2 - shift 2 - ;; -p | --pid | --parity) PID=$2 PARITY=$(echo "$2" | tr '[:lower:]' '[:upper:]') shift 2 ;; + -r | --rts) + RTS=$(echo "rts=$2" | tr '[:upper:]' '[:lower:]') + shift 2 + ;; + -v | --vid) + VID=$2 + shift 2 + ;; --) shift break From b33b5d738284cfd10e7b52bb55c13bd648cf45e1 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 21 Jul 2026 14:56:36 +0200 Subject: [PATCH 5/8] feat(stm32cubeprog): add -f/--freq for swd protocol Signed-off-by: Frederic Pillon --- stm32CubeProg.sh | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/stm32CubeProg.sh b/stm32CubeProg.sh index 745b47fce..3a369f08b 100644 --- a/stm32CubeProg.sh +++ b/stm32CubeProg.sh @@ -14,6 +14,7 @@ ADDRESS=0x8000000 START=0x8000000 ERASE= # Optional for SWD +FREQ= MODE=UR # Optional for Serial RTS= @@ -39,6 +40,7 @@ usage() { Specific options for SWD protocol: Optional: + -f, --freq SWD frequency in KHz. -m, --mode connection mode: UR (default), HOTPLUG, POWERDOWN or hwRstPulse Specific options for Serial protocol: @@ -124,12 +126,12 @@ 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:b:a:es:o:m:c:d:p:r:v: "$@"); then + if ! options=$(getopt hi:b:a:es:o:f:m:c:d:p:r:v: "$@"); then echo "Terminating..." >&2 exit 1 fi else - if ! options=$(getopt -a -o hi:b:a:es:o:m:c:d:p:r:v: --long help,interface:,bin:,address:,erase,start:,offset:,mode:,com:,dtr:,parity:,rts:,pid:,vid: -- "$@"); then + if ! options=$(getopt -a -o hi:b:a:es:o:f:m:c:d:p:r:v: --long help,interface:,bin:,address:,erase,start:,offset:,freq:,mode:,com:,dtr:,parity:,rts:,pid:,vid: -- "$@"); then echo "Terminating..." >&2 exit 1 fi @@ -167,6 +169,10 @@ while true; do OFFSET=$2 shift 2 ;; + -f | --freq) + FREQ=$2 + shift 2 + ;; -m | --mode) MODE=$2 shift 2 @@ -221,7 +227,20 @@ 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 + ${STM32CP_CLI} --connect "${PORT_PARAM}" mode="${MODE}" "${ERASE}" --quietMode --download "${FILEPATH}" "${ADDRESS}" --start "${START}" ;; dfu) if [ -z "${VID}" ] || [ -z "${PID}" ]; then From 744264d54a1f02f365fcf1429d0ce198f55f82a5 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 21 Jul 2026 16:32:03 +0200 Subject: [PATCH 6/8] feat(stm32cubeprog): add stlink serial number option Signed-off-by: bipoe Co-Authored-By: Frederic Pillon --- stm32CubeProg.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/stm32CubeProg.sh b/stm32CubeProg.sh index 3a369f08b..04faa7a2d 100644 --- a/stm32CubeProg.sh +++ b/stm32CubeProg.sh @@ -16,6 +16,7 @@ ERASE= # Optional for SWD FREQ= MODE=UR +SERIAL_NUMBER= # Optional for Serial RTS= DTR= @@ -42,7 +43,7 @@ usage() { 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,... @@ -126,12 +127,12 @@ 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:b:a:es:o:f:m:c:d:p:r:v: "$@"); then + if ! options=$(getopt hi:b:a:es:o:f:m:n:c:d:p:r:v: "$@"); then echo "Terminating..." >&2 exit 1 fi else - if ! options=$(getopt -a -o hi:b:a:es:o:f:m:c:d:p:r:v: --long help,interface:,bin:,address:,erase,start:,offset:,freq:,mode:,com:,dtr:,parity:,rts:,pid:,vid: -- "$@"); 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 @@ -177,6 +178,10 @@ while true; do MODE=$2 shift 2 ;; + -n | --snum) + SERIAL_NUMBER="$2" + shift 2 + ;; -c | --com) PORT=$2 shift 2 @@ -240,6 +245,9 @@ case "${INTERFACE}" in ;; 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) From 58794f61062f5606a30a31b84849a4cb839831af Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Wed, 22 Jul 2026 14:25:00 +0200 Subject: [PATCH 7/8] fix(stm32cubeprog): harden getopt support on MacOS - brew prefix usage - MacPorts support Fixes #115 Signed-off-by: Frederic Pillon --- stm32CubeProg.sh | 86 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 15 deletions(-) diff --git a/stm32CubeProg.sh b/stm32CubeProg.sh index 04faa7a2d..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= @@ -69,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 @@ -91,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 @@ -126,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:b:a:es:o:f:m:n:c:d:p:r:v: "$@"); 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 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 "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 From 9c1408baa0ed836a7863746b7dfff929dbc26543 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 23 Jul 2026 08:37:34 +0200 Subject: [PATCH 8/8] doc: update badge version to 2.5.0 Signed-off-by: Frederic Pillon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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.