Building a Blackmagic Debug Probe

The Black Magic debug probe is in-application debugger, which allows IDE’s like NetBeans, Eclipse or others to connect directly to the hardware without using bridges like for example Openocd. The Blackmagic Probe software is open source and available on this Github link.

There are several posts/instructions on the internet regarding how to load the Black Magic firmware either on ST-Link hardware debuggers, ST-Link clones or using the “blue pill” STM32F103C8T6 based board.

There are several possible issues with this board:

  1. First they are quite cheap – not an issue
  2. It seems on some versions there is a problem with the USB connector regarding a resistor and bad contacts. In my version I had no issues. It just worked fine.
  3. The on board chip is the STM32F103C8T6 which has 64Kb of flash, but some claim that it can have 128Kb. In my case all the boards that I have, the flash size is 64Kb.

This last issue is a show stopper at the current release of the Black Magic firmware since it won’t fit on the 64Kb flash of the ST32F103C8T6. We must cut things from the firmware to be able to flash it on the STM32F103C8T6 board. But we will see how to do that.

Downloading and compiling the firmware:
This step is just straight forward, just clone the Blacmagic repository and compile. Since we are compiling to ST32F103 board we will assume it is a ST-Link clone.

[pcortex@pcortex:opt]$ git clone https://github.com/blacksphere/blackmagic
Cloning into 'blackmagic'...
remote: Counting objects: 5029, done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 5029 (delta 1), reused 2 (delta 0), pack-reused 5020
Receiving objects: 100% (5029/5029), 2.01 MiB | 1.38 MiB/s, done.
Resolving deltas: 100% (3558/3558), done.
[pcortex@pcortex:opt]$ cd blackmagic/
README.md  Makefile  libopencm3/  HACKING  driver/  COPYING  scripts/  src/  upgrade/
[pcortex@pcortex:blackmagic|master]$ make
Initialising git submodules...
Submodule 'libopencm3' (https://github.com/libopencm3/libopencm3.git) registered for path 'libopencm3'
Cloning into '/opt/lixo/blackmagic/libopencm3'...
Submodule path 'libopencm3': checked out '67242de60dec0227739cd549e8a78e1a3c15dbf5'
  GENHDR  include/libopencm3/efm32/efm32gg/irq.json
  GENHDR  include/libopencm3/efm32/efm32g/irq.json
  GENHDR  include/libopencm3/efm32/efm32lg/irq.json
  GENHDR  include/libopencm3/efm32/efm32tg/irq.json
  GENHDR  include/libopencm3/stm32/f2/irq.json
...
...
...

Now we must target the firmware to our blue pill board, and so compiling the firmware as it was for a ST-Link clone:

[pcortex@pcortex:blackmagic|master]$ cd src
[pcortex@pcortex:src|master]$ make clean
 CLEAN
[pcortex@pcortex:src|master]$ make PROBE_HOST=stlink
GIT     include/version.h
  CC      target/adiv5.c
  CC      target/adiv5_jtagdp.c
  CC      target/adiv5_swdp.c
  CC      command.c
  CC      target/cortexa.c
  CC      target/cortexm.c
...
...
...
  CC      platforms/stlink/dfu_upgrade.c
  LD      dfu_upgrade
  OBJCOPY dfu_upgrade.bin
  OBJCOPY dfu_upgrade.hex

Done! On the src there is now at least two files:

  1. blackmagic_dfu.bin – The Device Firmware Upgrade loader.
  2. blackmagic.bin – The Blackmagic firmware.

Checking the file sizes we can see that the blackmagic.bin file (as of today) 57K, and the bootloader is 6.8K.

Flashing the firmware:
Flashing the firmware can be done by several forms:

  1. Using the STM32 embedded loader through a serial port
  2. Using the SWD connection, ST-Link probe and Openocd
  3. Using the SWD connection, ST-Link probe and Texane/st-link/st-util
  4. Using the DFU protocol, but it depends if the board already has a DFU firmware loaded.

Most of the posts on the internet regarding this step use the first aproach, namely using the STM32 boot loader and serial port. This needs a serial to USB converter to be connected and the STM32 boot pins to be modified.

Anyway, I’m flashing the firmware using Openocd and/or st-link utils through a ST-Link debug probe:

The blue pill pinout is as follows where the SWD connector is oposite the USB port:

From the ST-Link probe we need to connect the following pins:

  • Probe SWCLK Blue Pill DCLK
  • Probe SWDIO Blue Pill DIO
  • Probe GND Blue Pill GND

Regarding the power, I advise not to connect it and power up the blue pill board through the USB connector. This will allow to have access to both boards through USB without any possible power clashes.

We can now flash the firmware either with Texane St-Link programs or the AUR Arch Linux package stlink-git or using Openocd.

For using Openocd, create the following file and name it for example bluepill.cfg:

set CHIPNAME STM32F103C8T6

source [find interface/stlink-v2.cfg]
transport select hla_swd
source [find target/stm32f1x.cfg]
set WORKAREASIZE 0x2000

Also make sure that the ST-Link probe is detected so both st-link utils and openocd can work:

[pcortex@pcortex:src|master]$ lsusb
Bus 002 Device 003: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 008 Device 003: ID 046d:c52f Logitech, Inc. Unifying Receiver
Bus 008 Device 002: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
...
Bus 003 Device 008: ID 0483:3748 STMicroelectronics ST-LINK/V2

We can now flash our board with the following command using Openocd:

openocd -f ../bluepill.cfg -c ‘init_reset halt; program blackmagic_dfu.bin 0x8000000 verify; reset;exit’

[pcortex@pcortex:src|master]$ openocd -f ../bluepill.cfg -c 'init_reset halt; program blackmagic_dfu.bin 0x8000000 verify; reset;exit'
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
0x2000
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v24 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.208372
Info : STM32F103C8T6.cpu: hardware has 6 breakpoints, 4 watchpoints
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x080017b4 msp: 0x20005000
** Programming Started **
auto erase enabled
Info : device id = 0x20036410
Info : flash size = 64kbytes
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20005000
wrote 7168 bytes from file blackmagic_dfu.bin in 0.656939s (10.655 KiB/s)
** Programming Finished **
** Verify Started **
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000002e msp: 0x20005000
verified 6900 bytes in 0.187018s (36.030 KiB/s)
** Verified OK **
[pcortex@pcortex:src|master]$

Using the st-flash command as documented on STM as BMP

[pcortex@pcortex:src|master]$ st-flash write blackmagic_dfu.bin 0x8000000
st-flash 1.3.1
2017-06-13T20:26:01 INFO src/common.c: Loading device parameters....
2017-06-13T20:26:01 INFO src/common.c: Device connected is: F1 Medium-density device, id 0x20036410
2017-06-13T20:26:01 INFO src/common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 1024 bytes
2017-06-13T20:26:01 INFO src/common.c: Attempting to write 6888 (0x1ae8) bytes to stm32 address: 134217728 (0x8000000)
Flash page at addr: 0x08001800 erased
2017-06-13T20:26:01 INFO src/common.c: Finished erasing 7 pages of 1024 (0x400) bytes
2017-06-13T20:26:01 INFO src/common.c: Starting Flash write for VL/F0/F3 core id
2017-06-13T20:26:01 INFO src/flash_loader.c: Successfully loaded flash loader in sram
  6/6 pages written
2017-06-13T20:26:02 INFO src/common.c: Starting verification of write complete
2017-06-13T20:26:02 INFO src/common.c: Flash written and verified! jolly good!
[pcortex@pcortex:src|master]$

So far so good, but the above is just DFU firmware that allows to use DFU utils later to upgrade the firmware through the USB port without using any other tools.

If unplug and plug our blue pill board and check for the USB ports we have now:

[pcortex@pcortex:src|master]$ lsusb
Bus 002 Device 003: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 008 Device 003: ID 046d:c52f Logitech, Inc. Unifying Receiver
Bus 008 Device 002: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
...
Bus 003 Device 012: ID 1d50:6017 OpenMoko, Inc. Black Magic Debug Probe (DFU)
Bus 003 Device 008: ID 0483:3748 STMicroelectronics ST-LINK/V2
...

And we can now also use the dfu-util command to upload the firmware.

To upload the firmware we will see that it fails due to the firmware size and the 64Kb flash size. It might not happen to you if your board has more than 64Kb of flash available.

With Openocd command:

openocd -f ../bluepill.cfg -c 'init_reset halt; program blackmagic.bin verify; reset;exit'    
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
0x2000
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v24 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.208372
Info : STM32F103C8T6.cpu: hardware has 6 breakpoints, 4 watchpoints
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x080017b4 msp: 0x20005000
** Programming Started **
auto erase enabled
Info : device id = 0x20036410
Info : flash size = 64kbytes
Warn : no flash bank found for address 0
wrote 0 bytes from file blackmagic.bin in 0.016043s (0.000 KiB/s)
** Programming Finished **
** Verify Started **
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000002e msp: 0x20005000
Error: checksum mismatch - attempting binary compare
diff 0 address 0x08010000. Was 0xff instead of 0x00
diff 1 address 0x08010001. Was 0xff instead of 0x00
diff 2 address 0x08010002. Was 0xff instead of 0x00
diff 3 address 0x08010003. Was 0xff instead of 0x00
diff 4 address 0x08010004. Was 0xff instead of 0x00
diff 5 address 0x08010005. Was 0xff instead of 0x00
diff 6 address 0x08010006. Was 0xff instead of 0x00

....
diff 123 address 0x0801007b. Was 0xff instead of 0x00
diff 124 address 0x0801007c. Was 0xff instead of 0x00
diff 125 address 0x0801007d. Was 0xff instead of 0x00
diff 126 address 0x0801007e. Was 0xff instead of 0x00
diff 127 address 0x0801007f. Was 0xff instead of 0x00
More than 128 errors, the rest are not printed.
embedded:startup.tcl:476: Error: ** Verify Failed **
in procedure 'program' 
in procedure 'program_error' called at file "embedded:startup.tcl", line 520
at file "embedded:startup.tcl", line 476

With the st-flash command:

[pcortex@pcortex:src|master]$ st-flash --reset write blackmagic.bin 0x8002000
st-flash 1.3.1
2017-06-13T20:37:27 INFO src/common.c: Loading device parameters....
2017-06-13T20:37:27 INFO src/common.c: Device connected is: F1 Medium-density device, id 0x20036410
2017-06-13T20:37:27 INFO src/common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 1024 bytes
2017-06-13T20:37:27 INFO src/common.c: Attempting to write 58084 (0xe2e4) bytes to stm32 address: 134225920 (0x8002000)
2017-06-13T20:37:27 ERROR src/common.c: addr too high
stlink_fwrite_flash() == -1
[pcortex@pcortex:src|master]$ 

And with the dfu util forcing the write above 64Kb:

[pcortex@pcortex:src|master]$ sudo dfu-util -a 0 -s 0x08002000:leave:force -D blackmagic.bin
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 1d50:6017
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 1024
DfuSe interface name: "Internal Flash   "
Downloading to address = 0x08002000, size = 58084
dfu-util: Last page at 0x080102e3 is not writeable
[pcortex@pcortex:src|master]$ 

So no luck with my board version, and as a solution we need to strip down the firmware.

Striping down the firmware:
To make the BMP firmware able to fit the 64Kb flash we have to cut things. In my case I’ve removed some processors support since my work is with the STM32 and nRF families:

Edit the file named cortexm.c located at target subdirectory, and delete the following lines around line 254 (or search by PROBE) to remove the unneeded support:

#define PROBE(x) \
        do { if ((x)(t)) return true; else target_check_error(t); } while (0)

        PROBE(stm32f1_probe);
        PROBE(stm32f4_probe);
        PROBE(stm32l0_probe);   /* STM32L0xx & STM32L1xx */
        PROBE(stm32l4_probe);
        PROBE(lpc11xx_probe);
        PROBE(lpc15xx_probe);
        PROBE(lpc43xx_probe);
        PROBE(sam3x_probe);
        PROBE(sam4l_probe);
        PROBE(nrf51_probe);
        PROBE(samd_probe);
        PROBE(lmi_probe);
        PROBE(kinetis_probe);
        PROBE(efm32_probe);

Still at the source directory we build again the firmware:

[pcortex@pcortex:src|master]$ make clean
[pcortex@pcortex:src|master]$ make PROBE_HOST=stlink
[pcortex@pcortex:src|master]$ ls -l blackmagic*
-rwxr-xr-x 1 pcortex users 753K jun 13 20:53 blackmagic*
-rwxr-xr-x 1 pcortex users  55K jun 13 20:53 blackmagic.bin*
-rwxr-xr-x 1 pcortex users 325K jun 13 20:53 blackmagic_dfu*
-rwxr-xr-x 1 pcortex users 6,8K jun 13 20:53 blackmagic_dfu.bin*
-rw-r--r-- 1 pcortex users  20K jun 13 20:53 blackmagic_dfu.hex
[pcortex@pcortex:src|master]$

We can seen now that the firmware was “slim down” around 2K, which is enough now to fit the 64Kb flash:

Using Openocd:

[pcortex@pcortex:src|master]$ openocd -f ../bluepill.cfg -c 'init_reset halt; program blackmagic.bin 0x8002000 verify; reset;exit'
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
0x2000
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v24 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.208372
Info : STM32F103C8T6.cpu: hardware has 6 breakpoints, 4 watchpoints
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x080017b4 msp: 0x20005000
** Programming Started **
auto erase enabled
Info : device id = 0x20036410
Info : flash size = 64kbytes
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20005000
wrote 54272 bytes from file blackmagic.bin in 3.792976s (13.973 KiB/s)
** Programming Finished **
** Verify Started **
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000002e msp: 0x20005000
verified 53744 bytes in 0.854957s (61.388 KiB/s)
** Verified OK **

Using st-flash:

[pcortex@pcortex:src|master]$ st-flash --reset write blackmagic.bin 0x8002000
st-flash 1.3.1
2017-06-13T20:58:02 INFO src/common.c: Loading device parameters....
2017-06-13T20:58:02 INFO src/common.c: Device connected is: F1 Medium-density device, id 0x20036410
2017-06-13T20:58:02 INFO src/common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 1024 bytes
2017-06-13T20:58:02 INFO src/common.c: Attempting to write 55720 (0xd9a8) bytes to stm32 address: 134225920 (0x8002000)
Flash page at addr: 0x0800f800 erased
2017-06-13T20:58:05 INFO src/common.c: Finished erasing 55 pages of 1024 (0x400) bytes
2017-06-13T20:58:05 INFO src/common.c: Starting Flash write for VL/F0/F3 core id
2017-06-13T20:58:05 INFO src/flash_loader.c: Successfully loaded flash loader in sram
 54/54 pages written
2017-06-13T20:58:09 INFO src/common.c: Starting verification of write complete
2017-06-13T20:58:09 INFO src/common.c: Flash written and verified! jolly good!

Using the DFU firmware upload:

[pcortex@pcortex:src|master]$ sudo dfu-util -a 0 -s 0x08002000:leave:force -D blackmagic.bin
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 1d50:6017
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 1024
DfuSe interface name: "Internal Flash   "
Downloading to address = 0x08002000, size = 55720
Download        [=========================] 100%        55720 bytes
Download done.
File downloaded successfully
Transitioning to dfuMANIFEST state

And now if we unplug the blue pill board and connect it again we should have two new tty USB based ports:

[35014.003313] usb 3-2.4: new full-speed USB device number 20 using uhci_hcd
[35019.346373] cdc_acm 3-2.4:1.0: ttyACM0: USB ACM device
[35019.349364] cdc_acm 3-2.4:1.2: ttyACM1: USB ACM device

Success!

Starting using the BMP probe:

To start using our blue pill board as a Blackmagic probe we need the following information and configuration:

  1. Connect a LED (with a resistor…) to pin PA8 to show the probe activity.
  2. The target SWD pins are CLK at pin PA5 and DIO at PB14.
  3. The support for the USB to UART bridge (the second ttyACM1 port) is PA3 – RX and PA2 – TX

So we now can use the BM probe instead of a ST-Link probe, and connect the target board SWD pins to PA5 e PB14: CLK and DIO respectively.

The led will blink when the program is running or it will fast blink when loading a program into the target board.

More information on this video from no other than the builder of the Magic Probe to see more of the probe capabilities. I also recommend the Blackmagic probe wiki for further information.

A quick example with an nRF52 based board connected to the BMP by using the ARM GDB debugger arm-none-eabi-gdb directly:

(gdb) target extended-remote /dev/ttyACM0
Remote debugging using /dev/ttyACM0
(gdb) monitor swdp_scan
Target voltage: unknown
Available Targets:
No. Att Driver
 1      Nordic nRF52
(gdb) att 1
(gdb) monitor
Black Magic Probe (Firmware v1.6.1-25-gaaa7b0e-dirty) (Hardware Version 0)
Copyright (C) 2015  Black Sphere Technologies Ltd.
License GPLv3+: GNU GPL version 3 or later 


Interesting links:

Most of this post wouldn’t be possible without gathering information from around the web. Here is a set of information that might be useful to gather more or missing information from this post:

  1. Black Magic Probe (BMP) on ST-Link v2 clones
  2. STM Discovery as Black Magic Probe
  3. STM32Duino forum