Using Black Magic Probe With Teensy 4.1

I have added a 10 pin JTAG interface to a Teensy 4.1 following this guide. GitHub - SpenceV1/Teensy_41_Debug_PCB: Teensy 4.1 Debug PCB
I modified the flex PCB to have a 10 pin JTAG to use with a Black Magic probe. Black Magic bmscan.exe sees the probe on COM 14 - GDB and COM 15 Serial output. The issue I am running into is the PlatformIO Teensy package on VSCode does not see Blackmagic as a valid debug or uploader for Teensy 4.1. I did try modifying teensy41.json in the ~/.platformio/platforms/teensy/boards/ directory by adding Blackmagic to the list of upload protocols. This caused a manifest error when trying to upload.

Is there a way to modify the Teensy platform files so PlatformIO will allow the use of a Black Magic probe with Teensy41?

That’s only part of the needed mods. In platform.py

in main.py

You will need a custom fork of platform-teensy for a clean integration, local changes will be lost after an update.

Thanks @maxgerhardt

Edited to add: **** NVM. I found “blackmagic” has to be in the upload protocols in addition to “blackmagic-jtag”. Added it to the list and the error is gone.

The above got me closer. The upload via jtag part works when I comment out debug_tool & debug_port in the platformio.ini.

However, I am still getting the below error for the debug part if I uncomment the debug_ directives in platformio.ini. I have searched but I can not fild the list of debug tools the script is referencing.

Resolving teensy41 dependencies...
Already up-to-date.
Updating metadata for the vscode IDE...
UserSideException: Processing teensy41 (platform: teensy; board: teensy41; framework: arduino)
--------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
DebugInvalidOptionsError: Unknown debug tool `blackmagic`. Please use one of `jlink` or `custom`:
  File "C:\Users\chris\.platformio\penv\Lib\site-packages\platformio\builder\main.py", line 173:
    env.SConscript("$BUILD_SCRIPT")
  File "C:\Users\chris\.platformio\packages\tool-scons\scons-local-4.7.0\SCons\Script\SConscript.py", line 612:
    return _SConscript(self.fs, *files, **subst_kw)
  File "C:\Users\chris\.platformio\packages\tool-scons\scons-local-4.7.0\SCons\Script\SConscript.py", line 279:
    exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals)
  File "C:\Users\chris\.platformio\platforms\teensy\builder\main.py", line 162:
    target_elf = env.BuildProgram()
  File "C:\Users\chris\.platformio\packages\tool-scons\scons-local-4.7.0\SCons\Util\envs.py", line 251:
    return self.method(*nargs, **kwargs)
  File "C:\Users\chris\.platformio\penv\Lib\site-packages\platformio\builder\tools\piobuild.py", line 61:
    env.ProcessProgramDeps()
  File "C:\Users\chris\.platformio\packages\tool-scons\scons-local-4.7.0\SCons\Util\envs.py", line 251:
    return self.method(*nargs, **kwargs)
  File "C:\Users\chris\.platformio\penv\Lib\site-packages\platformio\builder\tools\piobuild.py", line 111:
    env.PrintConfiguration()
  File "C:\Users\chris\.platformio\packages\tool-scons\scons-local-4.7.0\SCons\Util\envs.py", line 251:
    return self.method(*nargs, **kwargs)
  File "C:\Users\chris\.platformio\penv\Lib\site-packages\platformio\builder\tools\pioplatform.py", line 233:
    _get_debug_data(),
  File "C:\Users\chris\.platformio\penv\Lib\site-packages\platformio\builder\tools\pioplatform.py", line 197:
    % board_config.get_debug_tool_name(env.GetProjectOption("debug_tool")),
  File "C:\Users\chris\.platformio\penv\Lib\site-packages\platformio\platform\board.py", line 126:
    raise DebugInvalidOptionsError(
========================== [FAILED] Took 1.01 seconds ==========================

Can you upload your current modded platform-teensy in its entirety?

I haven’t cloned the platformio repo yet. I zipped what is on the PC.

In platform.py, just replace the _add_default_debug_tools method with this exact code.

    def _add_default_debug_tools(self, board):
        debug = board.manifest.get("debug", {})
        upload_protocols = board.manifest.get("upload", {}).get(
            "protocols", [])
        if "tools" not in debug:
            debug["tools"] = {}

        if "jlink" in upload_protocols and "jlink" not in debug["tools"]:
            assert debug.get("jlink_device"), (
                "Missed J-Link Device ID for %s" % board.id)
            debug["tools"]["jlink"] = {
                "server": {
                    "package": "tool-jlink",
                    "arguments": [
                        "-singlerun",
                        "-if", "SWD",
                        "-select", "USB",
                        "-device", debug.get("jlink_device"),
                        "-port", "2331"
                    ],
                    "executable": ("JLinkGDBServerCL.exe"
                                   if IS_WINDOWS else
                                   "JLinkGDBServer")
                }
            }
        # blackmagic always possible
        debug["tools"]["blackmagic"] = {
            "hwids": [["0x1d50", "0x6018"]],
            "require_debug_port": True
        }
        board.manifest["debug"] = debug
        return board

Then when I have

[env:teensy41]
platform = teensy
framework = arduino
board = teensy41
upload_protocol = blackmagic
debug_tool = blackmagic
; specify COM port of Blackmagic debug probe (for GDB)
debug_port = COM3

And use the PIO Core CLI to start debugging from the command line

PS C:\Users\Max\Desktop\arduino-blink> pio debug --interface=gdb -- -x .pioinit
Preparing firmware for debugging...
Processing teensy41 (platform: symlink://C:\Users\Max\Desktop\teensy; framework: arduino; board: teensy41)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/teensy/teensy41.html
PLATFORM: Teensy (4.17.0) > Teensy 4.1
HARDWARE: IMXRT1062 600MHz, 512KB RAM, 7.75MB Flash
DEBUG: Current (blackmagic) External (blackmagic, jlink)
PACKAGES:
 - framework-arduinoteensy @ 1.157.220801 (1.57)
 - tool-teensy @ 1.159.0 (1.59)
 - toolchain-gccarmnoneeabi @ 1.50401.190816 (5.4.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 92 compatible libraries
Scanning dependencies...
No dependencies
Building in debug mode
Compiling .pio\build\teensy41\src\Blink.cpp.o
...
Archiving .pio\build\teensy41\libFrameworkArduino.a
Linking .pio\build\teensy41\firmware.elf
Checking size .pio\build\teensy41\firmware.elf
Calculating size .pio\build\teensy41\firmware.elf
Building .pio\build\teensy41\firmware.hex
teensy_size: Memory Usage on Teensy 4.1:
teensy_size:   FLASH: code:8708, data:3992, headers:8800   free for files:8104964
teensy_size:    RAM1: variables:4512, code:6272, padding:26496   free for local variables:487008
teensy_size:    RAM2: variables:12384  free for malloc/new:511904
============ [SUCCESS] Took 4.58 seconds ============
Reading symbols from C:\Users\Max\Desktop\arduino-blink\.pio\build\teensy41\firmware.elf...done.
PlatformIO Unified Debugger -> https://bit.ly/pio-debug
PlatformIO: debug_tool = blackmagic
PlatformIO: Initializing remote target...
.pioinit:19: Error in sourced command file:
(gdb) COM3: No such file or directory.

It definitely looks like it tries to access a COM port here, but I don’t have a BMP.

Black Magic is trying to connect. I get this error.

Reading symbols from C:\Users\chris\Documents\code\TestDebug.pio\build\teensy41\firmware.elf…
done.
PlatformIO Unified Debugger → Redirecting...
PlatformIO: debug_tool = blackmagic
PlatformIO: Initializing remote target…
Target voltage: 0.0V
SW-DP scan failed!
.pioinit:21: Error in sourced command file:
Attaching to Remote target failed

The issue I see is platformio is using the GDB command for SWD interface. The Teensy uses JTAG. Do you know where the command file is located that is being fed to GDB by platformio? I think that will need to be updated to send GDB the jtag_scan command vice the swdp_scan. Or it could send the auto_scan which will scan JTAG and SWD chains for connected devices.

Interesting. So when setting upload_protocol = blackmagic-jtag it does do the monitor jtag_scan command,

but with debug_tool = blackmagic, it’s hardcoded to do the swdp_scan.

I still think that you should be able to do a custom setup with

debug_tool = custom
; specify COM port of Blackmagic debug probe (for GDB)
debug_port = COM3
debug_init_cmds =
  target extended-remote $DEBUG_PORT
  monitor jtag_scan
  attach 1
  set mem inaccessible-by-default off
  $LOAD_CMDS
  $INIT_BREAK

See docs: https://docs.platformio.org/en/latest/projectconf/sections/env/options/debug/index.html

The hardcoded swdp_scan should also be fixed by PlatformIO… better open an issue for that!

Thanks so much for you help Max! Now I know where the problem lies so I can play around with the custom setup to get it right. Then I can submit a detailed issue to platformio.