Table of contents
- Why I got the STLink/v2 clones
- It didn't work
- Compiling Black Magic firmware and stlink-tool
- Flashing
- Using the STLink with Black Magic
In this project I've bought cheap STLink clones, found out they don't support debugging RP2040 and then fixed them using FOSS firmware replacement which also made them way better.
Why I got the STLink/v2 clones
I've been using spare Raspberry Pi Pico's as a Pico Probe1, that's Raspberry Pi's first party firmware for using any Pico board as a SWD debugger which can be used from OpenOCD. This feels quite janky, you need to remember which pins to use, you need a USB Micro-B cable and you need some special OpenOCD configuration.
I could buy the special Pico Probe board from Raspberry Pi but that still uses a USB Micro-B cable and their own special cables and more importantly I've also been having some issues with the debugger cutting out so I wanted something more reliable and convenient.
In school I've used an STLink debugger which I've never had any issues with, it was part of the Nucleo boards we used, but I know they're selling standalone debuggers too. When I searched for them I found they were pretty expensive (almost as much as a whole Nucleo board) but there was a lot of cheap clones available. Moreover the clones seem to have the perfect form-factor, the original STLink is a big ugly piece of plastic where the clones are shaped like a USB drive with the header at the end.
It didn't work
When they arrived in mail I've connected one to a Pico, ran OpenOCD and ooops.
> openocd -f /usr/share/openocd/scripts/interface/stlink.cfg -f /usr/share/openocd/scripts/target/rp2040.cfg
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Error: Debug adapter doesn't support 'swd' transport
/usr/share/openocd/scripts/target/rp2040.cfg:7: Error:
in procedure 'script'
at file "embedded:startup.tcl", line 28
at file "/usr/share/openocd/scripts/target/rp2040.cfg", line 7
What do you mean does not support SWD? That's its only job to support SWD. A quick search later and I found the answer.
It's true that the original ST-LINK firmware does not support multi-drop SWD debug protocol. RP2040 has two CPU cores, and multi-drop SWD support seems to be required even when you only want to connect to one of them.
-- jpa @ electronics.stackexchange2
The answer also mentioned a piece of very useful information - Black Magic3, an open source debug probe firmware also support this STLink clone hardware, adding support for many more targets than just STM8 and STM32 chips and also improving usability by removing the need for OpenOCD!
Compiling Black Magic firmware and stlink-tool
Black Magic uses a special purpose utility for flashing the firmware to an
STLink, stlink-tool
4. Unfortunately we'll need to run it every time we
plug in the STLink probe to switch it to the right mode, which is a bit annoying,
but it's still simpler than remembering how to use OpenOCD.
It depends on libusb1
, the current libusb
archlinux package worked for me.
> git clone --recursive https://github.com/blackmagic-debug/stlink-tool
[...]
> cd stlink-tool
> make
cc -std=c11 -Wall -Wextra -Werror -I/usr/include/libusb-1.0 -g -Og -D_DEFAULT_SOURCE -o src/main.o -c src/main.c
cc -std=c11 -Wall -Wextra -Werror -I/usr/include/libusb-1.0 -g -Og -D_DEFAULT_SOURCE -o src/stlink.o -c src/stlink.c
cc -std=c11 -Wall -Wextra -Werror -I/usr/include/libusb-1.0 -g -Og -D_DEFAULT_SOURCE -o src/crypto.o -c src/crypto.c
cc src/main.o src/stlink.o src/crypto.o tiny-AES-c/aes.o -lusb-1.0 -o stlink-tool
> sudo cp stlink-tool /usr/local/bin/
To build the firmware we'll need an bare metal ARM toolchain, fortunately the
arm-none-eabi-gcc
package on archlinux worked out of the box and I didn't need
to do any extra work^^
> git clone --recursive https://github.com/blackmagic-debug/blackmagic
[...]
> cd blackmagic
> meson setup build --cross-file cross-file/stlink.ini
[...]
User defined options
Cross files : cross-file/stlink.ini
Found ninja-1.11.1 at /usr/bin/ninja
> meson compile -C build
[...]
/usr/lib/gcc/arm-none-eabi/13.2.0/../../../../arm-none-eabi/bin/ld: region `rom' overflowed by 2568 bytes
Memory region Used Size Region Size %age Used
rom: 133640 B 128 KB 101.96%
ram: 12140 B 20 KB 59.28%
collect2: error: ld returned 1 exit status
[404/493] Compiling C object blackmagic.p/src_target_adiv5_jtag.c.o
ninja: build stopped: subcommand failed.
Oops again. I'll have to remove some target support to make the firmware smaller. Fortunately for me I don't need anything besides the RP2040 target, so I removed a few targets I thought I was least likely to need in the near future. While I was there I also enabled the use of SWIM pins for UART.
--- a/cross-file/stlink.ini
+++ b/cross-file/stlink.ini
@@ -18,7 +18,7 @@
[project options]
probe = 'stlink'
-targets = 'cortexm,hc32,lpc,nrf,nxp,renesas,rp,sam,stm,ti'
+targets = 'cortexm,nrf,nxp,rp,sam,stm,ti'
rtt_support = false
-stlink_swim_as_uart = false
+stlink_swim_as_uart = true
bmd_bootloader = false
And rebuild.
> meson setup build --cross-file cross-file/stlink.ini --wipe
[...]
User defined options
Cross files : cross-file/stlink.ini
Found ninja-1.11.1 at /usr/bin/ninja
> meson compile -C build
[...]
[388/482] Linking target blackmagic_stlink_firmware.elf
Memory region Used Size Region Size %age Used
rom: 117868 B 128 KB 89.93%
ram: 3724 B 20 KB 18.18%
[482/482] Linking target blackmagic
And now it builds :)
Flashing
To flash the firmware we need the STLink device to be in DFU (bootloader)
mode, this is the default mode it initializes in when connected. Running the
stlink-tool
utility without arguments runs the flashed code. Try it out by
plugging the device in and then run the utility twice.
> stlink-tool
ST-Link v2/v2.1 Bootloader found
Firmware version : V2J34S7
Loader version : 14152
ST-Link ID : 066BFC323148444257391531
Firmware encryption key : EF8725105916078C1BEBE2CE77DD7E21
Current mode : 1
> stlink-tool
ST-Link v2/v2.1 Bootloader found
Firmware version : V2J34S7
Loader version : 14152
ST-Link ID : 000000000000000000000000
Firmware encryption key : 1D05F6CAFEF730AA71439BC208172DA8
Current mode : 256
ST-Link dongle is not in the correct mode. Please unplug and plug the dongle again.
For the firmware that was flashed on mine this switched it to some mode 256
in
which it was no longer possible to flash. Reconnecting the device resets it back
to DFU mode. So we reconnect the device and then run the flashing command.
> stlink-tool build/blackmagic_stlink_firmware.bin
ST-Link v2/v2.1 Bootloader found
Firmware version : V2J34S7
Loader version : 14152
ST-Link ID : 066BFC323148444257391531
Firmware encryption key : EF8725105916078C1BEBE2CE77DD7E21
Current mode : 1
Type V2
....................................................................................................
After the animated dots the Black Magic firmware immediately runs, but next time
we connect the debugger we will need to run stlink-tool
without arguments to
run the firmware. In dmesg we see the debugger reconnecting as a new device as
we run stlink-tool
.
usb 2-2: new full-speed USB device number 24 using xhci_hcd
usb 2-2: New USB device found, idVendor=0483, idProduct=3748, bcdDevice= 1.00
usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 2-2: Product: STM32 STLink
usb 2-2: Manufacturer: STMicroelectronics
usb 2-2: SerialNumber: 3ÿj\x05AB714\x16\x19W
usb 2-2: USB disconnect, device number 24
usb 2-2: new full-speed USB device number 25 using xhci_hcd
usb 2-2: New USB device found, idVendor=1d50, idProduct=6018, bcdDevice= 1.09
usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 2-2: Product: Black Magic Probe (ST-Link/v2) v1.10.0-634-gfa79ab6b-dirty
usb 2-2: Manufacturer: Black Magic Debug
usb 2-2: SerialNumber: 066BFC323148444257391531
cdc_acm 2-2:1.0: ttyACM0: USB ACM device
cdc_acm 2-2:1.2: ttyACM1: USB ACM device
Those ttyACM0
and ttyACM1
devices correspond to the debugger and UART
adapter. On my device the SWCLK
and SWDIO
pins match their label, UART Tx is
on pin labeled RST
and UART Rx (the one reading from attached device) on pin
labeled SWIM
.
Using the STLink with Black Magic
Again, after plugging the debugger in we need to run the stlink-tool
once to
start the firmware. With the Black Magic firmware when we run it a second time
it won't show up as an STLink at all and won't do anything, it's ok to run it
more than once accidentally even while you're using the device.
> stlink-tool
ST-Link v2/v2.1 Bootloader found
Firmware version : V2J39S7
Loader version : 14152
ST-Link ID : 066BFC323148444257391531
Firmware encryption key : D026981A4C70D368E14F25B31CA48014
Current mode : 1
> stlink-tool
Trying to switch BMP/Application to bootloader
Can not open BMP/Application!
No ST-Link in DFU mode found. Replug ST-Link to flash!
We can use dmesg as shown above to find the TTY device names but if it's the
only serial device they'll always be ttyACM0
for the debugger and ttyACM1
for the UART adapter. To connect to the debugger we'll need a compatible GDB
build, on archlinux the arm-none-eabi-gdb
package worked for me.
> arm-none-eabi-gdb
GNU gdb (GDB) 14.2
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) target extended-remote /dev/ttyACM0
Remote debugging using /dev/ttyACM0
(gdb) monitor swd_scan
Target voltage: 3.23V
SWD scan failed!
Failed
(gdb)
Aha, we can see the SWD debugger but there is no device attached. Attaching a Rpi Pico using SWD and 5V pin to VBUS we get.
[...]
(gdb) monitor swd_scan
Target voltage: 3.23V
Available Targets:
No. Att Driver
1 Raspberry RP2040 M0+
2 Raspberry RP2040 M0+
3 Raspberry RP2040 Rescue (Attach to reset!)
(gdb) attach 1
Attaching to Remote target
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x10001f28 in ?? ()
(gdb)
Since we didn't call GDB with any specific file it attached to the Pico with whatever it was already running. So let's use the Pico Logic Anayzer from last time as an example.
[...]
(gdb) file ~/code/sigrok-pico/pico_sdk_sigrok/build/pico_sdk_sigrok.elf
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from ~/code/sigrok-pico/pico_sdk_sigrok/build/pico_sdk_sigrok.elf...
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/max/code/sigrok-pico/pico_sdk_sigrok/build/pico_sdk_sigrok.elf
^C
Program received signal SIGINT, Interrupt.
0x10003646 in sleep_until ()
(gdb) backtrace
#0 0x10003646 in sleep_until ()
#1 0x100036b0 in sleep_us ()
#2 0x10001a10 in main ()
(gdb)
There we go, a working debugger :)