This is the macOS guide for x3utils.
Important expectation check: this is not a .dmg app and there is no drag-to-Applications installer. The macOS version is a terminal-based tool, like the Linux version, but with an installer script that prepares the bundled OpenOCD build.
If you only want the shortest path, follow the beginner steps below. If you already use Homebrew and Terminal, jump to the advanced quick start.
Caution
SHU compatibility firmware limits: Do not use Flash SHU Compatible with F3/G3 VCU 1.6.3 or newer, or ZT3 VCU 1.5.9 or newer. GT3 is not supported by Flash SHU Compatible at any version (its own limit, VCU 1.7.2, is listed for reference only). SHU compat saves the original backup first, but using it on newer firmware may require restoring that backup.
- Install Homebrew from:
https://brew.sh
At the end of the Homebrew install, read the last lines carefully. Homebrew may print one or two commands that add brew to your shell path.
If you are not sure what that means, use the simple fix:
- close Terminal;
- log out of macOS;
- log back in;
- open Terminal again.
Then check:
brew --versionIf that prints a Homebrew version, continue.
- Download and unzip x3utils.
- Open the
x3utils_macfolder in Finder. - Right-click inside the folder and choose
New Terminal at Folder.
If you do not see that option:
- Open the
Terminalapp. - Type
cdwith a space after it. - Drag the
x3utils_macfolder into the Terminal window. - Press
ENTER.
Then run:
chmod +x installer.sh
./installer.sh
./launcher.shThe installer checks your Mac type, installs required Homebrew packages, sets executable permissions, and tests the bundled OpenOCD.
From the repository root:
cd x3utils_mac
chmod +x installer.sh
./installer.sh
./launcher.shIf Homebrew packages are already installed, brew install will usually skip or confirm them.
installer.sh:
- detects Apple Silicon (
arm64) or Intel (x86_64); - selects the matching bundled xPack OpenOCD folder;
- checks that Homebrew exists;
- installs
hidapi,libusb, andpython; - runs
chmod +xon scripts and OpenOCD; - tests that bundled OpenOCD can start.
Bundled OpenOCD folders:
xpack-openocd-0.12.0-7-darwin-arm64
xpack-openocd-0.12.0-7-darwin-x64
Homebrew is required by the current macOS installer.
Check if it is installed:
brew --versionIf that fails, install Homebrew first:
https://brew.sh
After installing Homebrew, close Terminal and open it again. If brew is still not recognized, log out of macOS and log back in.
Advanced users can also add Homebrew to the current shell manually.
Apple Silicon:
eval "$(/opt/homebrew/bin/brew shellenv)"Intel Mac:
eval "$(/usr/local/bin/brew shellenv)"If that works, follow the final PATH instructions printed by the Homebrew installer so the change is saved for future terminals.
The installer runs:
brew install hidapi libusb pythonUse System Information:
- Hold
Option. - Click the Apple menu.
- Choose
System Information. - Open
USB. - Plug and unplug the ST-LINK and check whether the USB list changes.
From Terminal, you can also run:
system_profiler SPUSBDataTypeIf the ST-LINK does not appear:
- try another USB cable;
- try another USB port or hub;
- avoid charge-only USB cables;
- check the adapter on another computer if possible.
After installation:
./launcher.shRun macOS scripts from Terminal. If something fails, keep the terminal open and copy the exact error text.
The main menu is:
- Check Connection
- Backup Full Memory (128 KB)
- Backup + Flash Loaded File
- Flash Slot 0
- Load / Change Target
.binFile - Advanced
- Exit
Option 3 uses the file loaded with Option 5. Flash Slot 0 and the Advanced flash actions keep their own prompts and do not reuse that loaded file.
Option 5 accepts only a full 128 KB (131072-byte) image, so its file cannot be used for Flash Slot 0, which takes a slot-sized payload instead. Flash Slot 0 asks for its own file for that reason.
The selected connection mode is saved in config.sh:
- A — Default / blinker buttons
- B — C45 / clone ST-LINK, with the guided hold/count/release flow
- C — C45 / genuine ST-LINK using nRST
- D — Power-race using fresh xPack OpenOCD processes to catch power-on
Mode B also exposes T to change the guided countdown timeout.
- Flash SHU Compatible
- Flash Only — No Backup
- Check Protection
- Unlock / Rescue — Mass Erase
- Back
Flash Only is deliberately dangerous because it skips the forced backup. It is
also the correct recovery path after rescue has left a confirmed blank chip;
the normal backup-required flash path rejects an all-0xFF dump.
Check Protection is read-only. Unlock / Rescue rewrites protection options and
can mass-erase main flash. It requires the explicit UNLOCK confirmation.
Both CLI actions honor launcher modes A/B/C/D. Flutter has its own separate
Mode-D protection block; that GUI restriction does not apply to this CLI.
Mode D is a best-effort power-on catch. macOS uses upstream xPack OpenOCD, which starts more slowly than the OEM OpenOCD builds used on Windows/Linux. Each dot is printed after one complete missed attempt, so pauses and uneven dot timing are normal.
Protection Check keeps retrying until one attempt contains the flash-bank, FAP,
and main-flash evidence needed for a verdict. After UNLOCK is confirmed,
Rescue similarly uses fresh attempts and reports success only after option-area
readback and rewrite-completion evidence.
Most users should use launcher.sh, but the lower-level scripts can be run directly.
./connection_test.shThis uses the connection mode currently saved in config.sh. It connects,
halts, and probes the flash bank without dumping or writing firmware.
./dump.shThis uses the connection mode currently saved in config.sh.
./flash.sh /path/to/firmware.binIf no path is supplied, flash.sh asks for one.
flash.sh validates the file, asks for confirmation, runs a backup first, then flashes and verifies.
./flash_slot0.sh
./flash_slot0.sh /path/to/firmware.binBacks up first, then writes slot 0 only. Without an argument it prompts for the
file. This uses the connection mode currently saved in config.sh.
./special/flash_compat.sh
./special/flash_only.sh
./special/rdp/rdp_check.sh -l
./special/rdp/rescue_unlock.sh -lflash_compat.sh uses python3 for its patch step. The flash scripts prompt
for their own file. -l tells the RDP tools to honor
the launcher mode saved in config.sh; without -l, they use the standalone
guided rescue connection. Rescue is destructive and still requires UNLOCK.
Protection Check saves one complete, ANSI-free transcript per run under
special/rdp/logs/. Existing logs under backup/ are left where they are;
Rescue retains its console-only behavior.
The launcher saves the selected connection mode by editing:
config.sh
If you run connection_test.sh, dump.sh, flash.sh, flash_slot0.sh, or
special/flash_compat.sh directly, they use the last connection mode selected
in the launcher.
If you are not sure:
- run
./launcher.sh; - select
A,B,C, orD; - exit or continue from the launcher;
- then run the direct script.
installer.sh
Prepares macOS dependencies and executable permissions.
launcher.sh
Main terminal menu.
connection_test.sh
Runs a read-only ST-LINK and target connection check using the saved mode.
dump.sh
Runs a full 128 KB dump using the saved connection mode.
flash.sh
Flashes a selected .bin file after validating it and forcing a backup first.
flash_slot0.sh
Backs up first, then writes slot 0 only. Boot, slot 1, and user data stay untouched.
validate_bin.sh
Shared macOS .bin validator used by flashing scripts.
race_grade.sh
Power-race attempt classifier used by mode D.
config.sh
Selects the correct bundled OpenOCD build and stores the selected connection mode, target configuration, and timeout.
xpack-openocd-*
Bundled OpenOCD builds for Apple Silicon and Intel Macs. Each bundle includes
the macOS-specific upstream Artery target configs, including mode D's
target/artery/at32f4x_race.cfg.
special/
Advanced SHU Compatible, Flash Only, and protection/rescue scripts. Read
special/notes.txt before using anything there.
Homebrew is not installed
Install Homebrew from https://brew.sh, then rerun:
./installer.shbrew: command not found
Homebrew may be installed, but Terminal does not know where to find it yet.
Beginner fix:
- close Terminal;
- log out of macOS;
- log back in;
- open Terminal;
- run
brew --version.
Advanced quick fix for Apple Silicon:
eval "$(/opt/homebrew/bin/brew shellenv)"Advanced quick fix for Intel Mac:
eval "$(/usr/local/bin/brew shellenv)"Then rerun:
./installer.shUnsupported architecture
The bundled macOS OpenOCD builds currently support arm64 and x86_64.
OpenOCD binary is not executable
Run:
chmod +x xpack-openocd-0.12.0-7-darwin-*/bin/openocdor rerun:
./installer.shPermission denied when running a script
Run:
chmod +x *.shmacOS blocks a downloaded script or binary
If macOS shows a security warning, open System Settings, check Privacy & Security, and allow the blocked item if you trust this x3utils download.
ST-LINK does not appear in USB devices
Check cable, port, hub, and adapter. macOS cannot use an adapter that does not appear as a USB device.
python3: command not found
Run:
brew install pythonconfig.sh is not writable
Run:
chmod u+w config.shMode-D dots pause or move unevenly
This is normal with xPack OpenOCD. Each dot represents a finished attempt, not a timed animation. Apply power as prompted and let the fresh-process loop keep trying.
Bin file contains only a single repeated byte value after rescue
A successful protection rescue can leave main flash blank (0xFF). The normal
Backup + Flash path rejects that dump by design. Use Advanced → Flash Only to
restore a known-good full 128 KB image, then return to normal backup-required
operations.
Terminal output is hard to read after failure
Run the script from Terminal instead of double-clicking it. Copy the exact error text when asking for help.