Black magic probe out of cheap STLink programmers
If you have ever worked with ARM Cortex M processors you’ve probably used GDB + OpenOCD combo for debugging. If you didn’t: OpenOCD connects to the processor via a STLink programmer and opens a socket to which GDB can connect. It will push data necessary for debugging (and understandable for GDB) through this socket. That means that if you connect GDB to this socket (so called remote debugging) you can debug processor’s software like any other application on your PC.
Usually you connect the microcontroller through the SWD interface pins to the STLink debugger/programmer which you then plug into your PC. Then you can start OpenOCD like so:
openocd -f interface/stlink-v2.cfg -f board/the_board.cfg \
-c 'reset_config trst_and_srst'
By default all of the OpenOCD’s scripts are stored in /usr/share/openocd/scripts
(assuming you are running Linux and have installed OpenOCD through you package manager).
If you are developing for a specific board (Nucleo, Discovery or anything like
that) you can find scripts for that in /usr/share/openocd/scripts/board
but
if you target a specific processor (and you can do that even if you are using
a development board) look in /usr/share/openocd/scripts/target
.
You also have to supply an interface script. Those are stored in
/usr/share/openocd/scripts/interface
(i.e. those programmers use the stlink-v2.cfg
).
Assuming OpenOCD connected fine, the next step is to connect GDB to the OpenOCD. Assuming default parameters it goes something like this:
arm-none-eabi-gdb --eval-command="target remote localhost:3333" firmware_binary.elf
This starts GDB with the binary that previously got flashed into processor’s memory
(GDB isn’t running the binary but it needs it as an argument to read the debug symbols).
The --eval-command
connects to the remote target on start. The OpenOCD runs
on the same machine and listens on the port 3333 (localhost:3333
). At this
point you can start debugging with GDB. That’s a bit of work to be able to step
through the code.
That’s where Black Magic Probe comes in. Imagine you can put everything I’ve describe above on the STLink programmer chip. You connect the STLink programmer to the micro controller and plug it into PC. You start GDB and you can step through the code. The whole OpenOCD part gets automated. That’s what Black Magic Probe does for you. It’s a STLink programmer/debugger with OpenOCD and GDB sessions on board.
The original creators of Black Magic Probe are BlackSphere Technologies. The project itself is open source. You can find it here. You can buy the Black Magic Probe board for around 60$. You can also make it for around 4$. This post is about making one. Take in consideration that buying one from an official distributor supports this project.
4$ magic <
The idea is to buy two STLink programmers and use one of them to flash the Black Magic Probe firmware onto the other one. You can get one of those for less than 2$.
After you get them in your hands you’ll find you can easily slide the enclosure off. You’ll find that those programmers are using the STM32F101CBT6 microcontrollers. In the image below you can see the four vias in the bottom left corner of the pcb. That’s the SWD header which is used to flash the microcontroller. That basically means you can reflash this programmer and use it like a generic development board.
I’ve received some unique programmers… they didn’t have vias but pads and the pinout was different… It took a few minutes to figure out which pad is which pin of STLink SWD connector. I’ve cut the wires I got with the programmers (both ends were female Dupont) and soldered them to the pads.
So at this point one of the dongles does what it’s meant to do - it’s a programmer and the second one is being operated on. Lets get the firmware source and start flashing.
git clone https://github.com/blacksphere/blackmagic.git
Quick build:
cd blackmagic
make
cd src
make clean
make PROBE_HOST=stlink
The firmware is based on libopencm3 - an open source low level hardware library for Cortex-M devices. Open source means transparent and that’s always a good thing. Especially when something goes wrong and needs debugging.
Before the programmer can be flashed, the memory needs to be unlocked for writing:
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
-c "init; reset halt; stm32f1x unlock 0; reset halt; exit"
I have erased the programmer’s firmware (here, using the small utility - st-link):
st-flash erase
I’ve flashed the, previously built, binary of the DFU (Device Firmware Update) bootloader to the beginning of the flash memory. It allows for updating the actual Black Magic Probe firmware.
st-flash write blackmagic_dfu.bin 0x8000000
The Black Magic Probe firmware gets written 8192 bytes further:
st-flash --reset write blackmagic.bin 0x8002000
For me everything went smoothly. I could desolder the wires from the flashed
dongle and put it back into the enclosure. I’ve connected it to the Linux PC
and run lsusb
:
...
Bus 002 Device 003: ID 1d50:6018 OpenMoko, Inc. Black Magic Debug Probe (Application)
...
And with that output I knew I didn’t screw up completely… I also run dfu-util -l
to
verify the DFU bootloader is being detected.
...
Found Runtime: [1d50:6018] ver=0100, devnum=5, cfg=1, intf=4, path="26-1", \
alt=0, name="Black Magic Firmware Upgrade (STLINK)", serial="D6CE8AB1"
...
Well, this looks great!
For the final check I looked at dmesg
output and verified that two serial
ports have been added to the /dev
directory, after connecting the probe.
For me those were ttyACM0
and ttyACM1
. Former is the one that GDB
will connect to while the latter is the debug UART.
In order to connect GDB to the proper port and the processor that I want to debug and control I run:
arm-none-eabi-gdb -ex "target extended-remote /dev/ttyACM0" binary.elf
(gdb) monitor swdp_scan
(gdb) attach 1
More Black Magic Probe commands can be found here. The wiki has a lot of great information so it’s worth going through it.
My next project involves some proper, low-level development on Cortex-M processor which means I’ll be able to play around with this new artifact. Can’t wait!
Update: I’ve been using the Black Magic Probe for some time now. Unfortunately
it is slightly less reliable than the usual OpenOCD + GDB combo. Sometimes
continuing after a break point locks the GDB - it just stops responding to commands
(even CTRL+C
or CTRL+D
signals). I find myself going back to the old way of doing
this. I still consider this project to be an interesting thing. I just don’t know if
it’s a professional tool that improves the workflow. Doesn’t seem like it.