BlackMagic Probe, VSCode, Excellent Cortex-Debug. UPDATED

I finally was able to program a clone stlink-v2 with the BlackMagic probe software completely on the Mac. Note that the STM32CubeIDE software is installed on my Macintosh. Also, the setup for my VSCode follows the previous instructions on this site for PSOC5 programming and working with STM32CubeMX.

If you do not have the pre-requisites installed, BlackMagic Probe will most likely not be compiled and programmed properly. I used the first STLink-v2 clone (see previous posts to set it up properly) to program the second one.

For setting up the BlackMagic probe from a clone STLink-v2, I followed the instructions on this page: https://ciesie.com/post/black_magic_probe_stlink/. Note that the STM32F103x devices list 32kB or 64kB of flash but usually have 128kB of flash. Some of the time, this flash did not pass system test, so your blackmagic probe may be unstable if you do not use a device with enough official flash in it.

The instructions from the ciesie site worked until the point of using openocd program to unlock memory, etc. To fix the problem I encountered, which was traced to an unexpected CPUID (the clone ID starts with an 0x1 rather than an 0x2), copy the stlink-v2.cfg file from your existing openocd directory into the src directory you are running openocd from to unlock the processor. If you followed the setups from previous installs, the stlink-v2.cfg file will probably be here: /Applications/VSCode_OnethinxPack_macOS/tools_2.0/openocd/scripts/interface/stlink-v2.cfg.

I then renamed the .cfg file to mystlink-v2.cfg and put the following text into the file:

echo "WARNING: This config file changes CPUTAPID "
source [find interface/stlink.cfg]
set CPUTAPID 0x2ba01477

The command to run the unlock then becomes the following from within the src directory. Note that the -f option starts searching in the current directory, and so it will find your .cfg file first:

openocd -f mystlink-v2.cfg -f target/stm32f1x.cfg \
        -c "init; reset halt; stm32f1x unlock 0; reset halt; exit"

Based on my experience, everything else in the instructions works the same, until the dfu test (not available on the Macintosh). A substitute for that is to run the ls command on the /dev directory like this:

ls -l /dev/cu.*
/dev/cu.BLTH			/dev/cu.S05A			/dev/cu.usbmodem4C99B0AB1
/dev/cu.Bluetooth-Incoming-Port	/dev/cu.URT1			/dev/cu.usbmodem4C99B0AB3

The cu.usbmodem4C99B0AB1 is the GDB port. The other one (cu.usbmodem4C99B0AB3) is a debug serial port. I have not researched accessing that port, as it requires soldering wires to the internals of the STLink clone and connecting them to your board.

In the following launch.json file, change the above /dev/cu.usbmodem4C99B0AB1 entry to match the one on your machine. (On Linux, it is usually /dev/ttyACM0. Also, on Linux, you may have to place your user in the dialout group to access that i/o port, or use sudo to make /dev/ttyACM0 world read/write/execute. Google is your friend for determining that.)

Setup For Debug

To debug with the BlackMagic probe, I added the following to my launch.json file. Note that I am debugging the blink2 test build. Change to your build name and .elf location. BlackMagic was able to load and launch. Unfortunately, this is the WRONG launch.json script to use with cortex-debug extension! The correct one is after this one. However, this partially works:

{
            "name": "Black Magic Probe",
            "type": "cppdbg",
            "request": "launch",
            "preLaunchTask": "Build STM",
            "cwd": "${workspaceRoot}",
            "MIMode": "gdb",
            "targetArchitecture": "arm",
            "logging": {
                "engineLogging": true
            },
            "program": "${workspaceRoot}/build/blink2.elf",
            "miDebuggerPath": "arm-none-eabi-gdb",
            //"miDebuggerServerAddress": "/dev/cu.usbmodem4C99B0AB1",
            "customLaunchSetupCommands": [
                {
                  "text": "cd ${workspaceRoot}"
                },
                {
                  "text": "target extended-remote /dev/cu.usbmodem4C99B0AB1" /* replace with your COM or /dev/ttyX */
                },
                {
                  "text": "monitor swdp_scan"
                },
                {
                  "text": "attach 1"
                },
                {
                  "text": "file ./build/blink2.elf"
                },
                {
                  "text": "load"
                },
                {
                    "text": "cd ${workspaceRoot}" /* set bath back so VScode can find source files */
                },
                {
                  "text": "set mem inaccessible-by-default off"
                },
                {
                  "text": "break main"
                }
              ],
            "serverLaunchTimeout": 10000,
            "windows": {
                "miDebuggerPath": "arm-none-eabi-gdb.exe"
            }
        }

I was able to single step and set a breakpoint and also set watch variables.

I was not able to interrupt a running program! The pause button was non-functional. Setting breakpoints while running did not work. If the executable encountered a breakpoint, the it would halt, and GDB had full control. You can then set a new breakpoint and do other things. Make sure you can force a breakpoint to be reached either through an interrupt handler/breakpoint combo or some other trick.

When I googled, I found complaints about these issues. Suggested configuration fixes I found applied if GDB is being run on a network port, but not for GDB running off of a serial port. (At least for a VSCode host).

The Fix: cortex-debug extension

I did not understand launch.json. I do not really understand launch.json, but I am getting better.

Regardless, I contacted Marus about this issue. Marus pointed out my problem. RTFM to me. IT IS NOT A CORTEX-DEBUG ISSUE. It is a MICROSOFT debugger issue. The “type”: “cppdbg”, field specifies the debugger!

The issue created by the type: “cppdbg” launch.json script is it launches Microsoft’s debugger! Here is a launch.json script for cortex-debug that works, interrupts the program, programs the file, etc. Two flavors are presented. BMP attach attaches to the current running device. BMP Debug programs the new code, executes, and breaks at the “main” function:

        {
            "name": "BMP attach",
            "cwd": "${workspaceRoot}",
            "executable": "${workspaceRoot}/build/blink2.elf",
            "request": "attach",    // "launch" also works perhaps
            "type": "cortex-debug",
            "servertype": "bmp",
            "interface": "swd",
            "device": "STM32F103",
            "BMPGDBSerialPort": "/dev/cu.usbmodem4C99B0AB1",  // Use whatever serial port makes sense for your OS and BMP setup
        },
        {
            "name": "BMP Debug",
            "cwd": "${workspaceRoot}",
            "executable": "${workspaceRoot}/build/blink2.elf",
            "request": "launch",    
            "preLaunchTask": "Build STM",
            "type": "cortex-debug",
            "servertype": "bmp",
            "interface": "swd",
            "device": "STM32F103",
            "BMPGDBSerialPort": "/dev/cu.usbmodem4C99B0AB1",  // Use whatever serial port makes sense for your OS and BMP setup
            "runToEntryPoint": "main"

        }
        

To this date, I have had zero issues with the cortex-debug extension! That is a remarkable statement, especially for my ability to make mistakes. That extension for Arm debugging is so far the best I have seen.

Fini

Setting up for BlackMagic does indeed work. If you are using stm32-for-vscode, the ST-extension select programmer for VScode is not used. If you try to use that selector, you will find that Black Magic is not in the list.

After the creation of a correct launch.json, it looks like the BlackMagic probe is a good choice for a debugger if it supports your processor family. There does not appear to be contractual issues with it.

Using a manufacturer dependent debugger probe is usually the best for an inexpensive probe, but it is tied contractually to a device or device family.

Using an independent JLink may be the best if you can afford it.

Using an STLink (as previous posts described) seems to be a decent way to go at the moment, but it is contractually tied to STM device families.

Enjoy!

Add a Comment

Your email address will not be published. Required fields are marked *