Black Magic Jtag

1 view
Skip to first unread message

Heidi Hall

unread,
Aug 3, 2024, 10:13:28 AM8/3/24
to nabarbductland

Anyways, I followed the excellent instructions in Converting an STM32F103 board to a Black Magic Probe. Build the Black Magic firmware for STM32F103, flash the DFU over serial, then use dfu-util to upload the firmware over USB. Reattach and system_profiler SPUSBDataType now shows the Black Magic and also two virtual serial devices appear in /dev:

The first is for attaching to GDB, when the blue pill is connected to a processor using SWD as follows: SWDIO=B14, SWCLK=A5. The second is a bonus free serial port, to be wired as follows: RXD=PA3, TXD=PA2. I confirmed the serial port operation by wiring it to another USB-to-serial adapter, then connecting with screen to both and typing in one, showing characters received on the other side.

But since we do have SWD/JTAG, how about making use of it? We could debug another STM32, but the ESP32 I used in Espressif IDF IoT Development Framework on the WEMOS LOLIN32 ESP32 to drive an SSD1305 OLED display over SPI without Arduino supports JTAG. Found on the ESP32.com forums, the link to this diagram which showed GPIO14 to TMS (test mode select), GPIO12 to TDI (test data input), GPIO13 to TCK (test interface clock), GPIO15 to TDO (test data output). Check the pinout for Black Magic Probe in src/platforms/stlink/platform.h:

Espressif has ported OpenOCD to support the ESP32 processor and the multicore FreeRTOS, which will be the foundation of most ESP32 apps, and has written some tools to help with features OpenOCD does not support natively.

Building OpenOCD from Sources for MacOS explains you need to use their fork of OpenOCD in -esp32. How does OpenOCD-ESP32 differ from the official upstream version, I forked the repo and created a pull request to show the differences: 176 commits, 80 files changed, +13,468 -127. What is the common ancestor? git merge-base esp32 master pinpoints this commit from May 21, 2016. Here are all the changes Espressif added:

The quickest and most convenient way to start with JTAG debugging is by using ESP32 WROVER KIT. Each version of this development board has JTAG interface already build in. No need for an external JTAG adapter and extra wiring / cable to connect JTAG to ESP32. WROVER KIT is using FT2232H JTAG interface operating at 20 MHz clock speed, which is difficult to achieve with an external adapter.

If you decide to use separate JTAG adapter, look for one that is compatible with both the voltage levels on the ESP32 as well as with the OpenOCD software. The JTAG port on the ESP32 is an industry-standard JTAG port which lacks (and does not need) the TRST pin. The JTAG I/O pins all are powered from the VDD_3P3_RTC pin (which normally would be powered by a 3.3V rail) so the JTAG adapter needs to be able to work with JTAG pins in that voltage range.

On the software side, OpenOCD supports a fair amount of JTAG adapters. See -Adapter-Hardware.html for an (unfortunately slightly incomplete) list of the adapters OpenOCD works with. This page lists SWD-compatible adapters as well; take note that the ESP32 does not support SWD. JTAG adapters that are hardcoded to a specific product line, e.g. STM32 debugging adapters, will not work.

The minimal signalling to get a working JTAG connection are TDI, TDO, TCK, TMS and GND. Some JTAG debuggers also need a connection from the ESP32 power line to a line called e.g. Vtar to set the working voltage. SRST can optionally be connected to the CH_PD of the ESP32, although for now, support in OpenOCD for that line is pretty minimal.

So what hardware can do this? Seems simple enough, hardware capable of driving four signals: TDI, TDO, CK, and TMS, but surprisingly difficult, at least for me. For now, I shelved this effort, and moved on towards debugging an ARM target.

Start with the libopencm3-examples. The stm32/f1 directory has quite a few boards. Some examples will require changes for the blue pill, at least changing the LED to PC13 instead of whatever the other boards used.

for contrast, all of the blackmagic/src/*.bin files are just data. Hmm.. and miniblink compiles to 101 KB miniblink.elf, how can it be so large? Largely redundant, 29 KB gzipped. But the blue pills have only at least 64 KB flash (sometimes/often unofficially 128 KB). The complete Black Magic firmware, minus the bootloader, is 60 KB. What am I missing?

To quickly and conveniently use the Black Magic Probe, I put together a couple simple shell scripts.The first, bmp_debug.sh, runs ARM GCC with the Black Magic Probe as a remote target (note you may need toedit the device node path for your system) and runs a JTAG and SWD scan, then drops you into gdb:

The second, bmp_flashstm32.sh, runs stm32loader.py (edit to add thefull path on your system if necessary, also check the device node) to erase teh flash, write a .bin file,and verify the flash; this is used for uploading new code to the target blue pill:

This is based on a simplified stm32-h103/miniblink from the official examples. To go deeper, learning more low-level, I also replaced these function calls with direct register accesses in this example:

This works identically, but produces slightly smaller code since the library functions are not needed. Can we go even lower-level? What about programming with no library at all? First step is to replace the constant definitions, this can be accomplished by running the code through the C preprocessor, arm-none-eabi-cpp pill_blink.c -DSTM32F1 -I libopencm3/include. The #includes can now be removed, however, libopencm3 provides something else crucial: the linker script.

The second log extract looks better as a target is detected. However, it looks as if the Black Magic Probe does not properly identify the MCU and therefore has no suitable memory map for the device. Do you have a recent version of the Black Magic Probe firmware? LPC1768 support was added about 18 months ago.

I followed this instruction: Upgrading Firmware blackmagic-debug/blackmagic Wiki GitHub
Once without pressing the button while plugging the BMP in and once while pressing the button. downloaded the nightly build, checked for the latest git hash and ran that dfutil command.

Is there a possibility that I need to set some jumper differently, in order for the debug interface to work, as that board comes by default with a ulink-me probe, which I could get to kind of work with the help of Maximilian Gerhardt(giant thanks btw), but failed to flash stuff on the hardware without using the Mbed framework.

So it seems to be a super weird behavior of the BMP.
I do not think that it is any hardware fault, but that you need to explicitly connect the probe into the board first and then connect it to the USB port of your computer.

I got a radio MCU which connects to cloud and can receive binaries from database. And I got a STM32 that controls some stuff, including other MCUs. In production this means a lot of headers and programming time for all of them, no way to update remotely, and even if the code is thoroughly tested - glitches are still possible.

So I want to connect things in a chain, so that if something apart from the radio crashes - radio MCU could re-flash the whole system. This of course could be done with UART when using bootloaders, but this again means you have to pre-program bootloaders on MCUs, and there's still a very slim chance it might fail.

So I need an example of how one MCU can flash another via JTAG or SWD (preferably), and then verify the result. From there I could get it to work on Arduino / STM / AVR / radio ARM. What I really want is a proof of concept simple test example to show it works with the peripheral (bit banging is always possible, but surely there is a smarter way to do it using existing MCU resources), before I go ahead and order prototype boards.

In general this should not be black magic, we've all got some Nucleo boards, which are a great example that programming STM32 with STM32 is possible. On my NucleoF722ZE, the STM32F103CBT6 does the programming. It should receive packets via USB, then program the main MCU via either JTAG or SWD. It has a pair of jumpers - CN4, when closed - the jumper connects T_JTCK with SWCLK, and T_JTMS with SWDIO, and programs the big MCU via SWD interface.


So it's not like there is no information on the topic. Almost all the code I found seems to bit-bang the data. I find it hard to believe that both JTAG and SWD on all STM32-based programmers are wired to SPI peripheral by pure coincidence :D Especially after that last repo for ESP32, which reads it via SPI.

It looks like the best approach is to adopt Paul Freund's project to some Arduino board and check out if it works fine. In the meantime, if anyone knows of original STM32 STlink source, or SWD example, or Arduino/STM32/AVR source that uses SPI to do SWD, to upload the flash to STM32 and check if it uploaded correctly - please drop a comment.

Hi. Yes I know it would be less complex, but you're missing the point. Every ST-LINK does it, and there's a bunch of projects where people have done it. So non-triviality doesn't matter - it's done. In most cases it's done with bit-banging which is usable and portable, but not the best way to do it IMHO. So I did a bit of research and found out it has also been implemented over SPI by few awesome people.

I can try to adapt the code from PaulFreund or lupyuen, and I will do so if I need to. But it will take days to rewrite and test, and I don't want to reinvent the wheel if it's already been done by smart people, or ST have since published their sources, and I just didn't think to look for sources in the most obvious place.

So perhaps my explanation of what I wanted to achieve was a bit blurry - I am looking for an easier to use example, not alternatives or reasons to not do it :D While looking for materials, I've seen some 15+ people trying to do the same thing to simplify their production, not to mention those who try to clone ST-link for whatever reasons, so I believe this is a useful exercise.

Thanks for your input, this is of course good to remember. Yet this is a slightly different topic. I've really started this hoping that someone might add more information to the links I collected - solutions that are easier to port or test out, vids with explanations, links to repos.

c80f0f1006
Reply all
Reply to author
Forward
0 new messages