April 28, 2024

A hobos guide to OpenOCD, part 1

I decided to roll up my sleeves and learn more about OpenOCD. I have tripped across it before, but I once again ran into the OpenOCD Users Guide. It is an intimidating 233 pages. The version I am looking at is dated April 22, 2024, only 6 days old!

Previous experience

Up to now I have used it primarily for STM32 projects, specifically with my ST-Link v2 dongles that I use to work with such boards. I used to use OpenOCD simply to flash code into the STM32 boards I was working with -- and it works fine for that. I have since discovered "st-flash" (available for Fedora as part of the "stlink" package). It allwos me to flash code with a single line like this:
st-flash write dirtyjtag.bluepill.noloader.bin 0x08000000
I have also used OpenOCD along with the ST-link v2 to do some debugging. I was shocked and amazed to discover that I could use openOCD along with gdb and single step my way through bootrom code.

I am now interested in learning what I can do with openOCD on my Zynq based boards (like the Ebaz-4205 and the Zeboard). Can I single step through the bootrom code? Can I download and run executables? How useful is OpenOCD without also using gdb along with it?

I am using "Versaloon" as a USB to JTAG "adapter" for the Zynq boards. I also have a XVC (Xilinx Virtual Cable) available via an xvc-pico adapter. The latter works fine with Vivado, but it is unclear how or if it can be used with OpenOCD.

Basic orientation

OpenOCD runs as a server -- I typically dedicate a window to run it in. The server starts us, connects to the adapter you specify and then offers services on several TCP network ports. I have yet to ever use the Tcl port, but there it is waiting for Tcl commands. The gdb port is not intended for human use, but you can connect gdb to it and then use gdb to manipulate your target. The telnet port allows "ordinary" interaction with OpenOCD using the normal OpenOCD commands. Type "exit" to the telnet port as needed.

Example use from my STM32F103 projects

This is a handy reminder for me, but a person reading this as their first introduction to OpenOCD will probably want to just skip to the next section, at least for now.

The STM32F103 is a popular $2 board commonly known as the "blue pill".
I used to flash code to it as follows (these days I use st-flash):

openocd $(OCDCFG) -c "program blink.elf verify reset exit"
This would typically be part of a Makefile, and I may as well just show that here:
OCDCFG = -f /usr/share/openocd/scripts/interface/stlink-v2.cfg -f /usr/share/openocd/scripts/target/stm32f1x.cfg

flash:  blink.elf
        openocd $(OCDCFG) -c "program blink.elf verify reset exit"

old_flash:
        @echo "type: flash write_image erase blink.bin 0x08000000"
        telnet localhost 4444
gdb:
        $(GDB) --eval-command="target remote localhost:3333" blink.elf

gdbtui:
        $(GDB) -tui --eval-command="target remote localhost:3333" blink.elf
The OCDCFG variable has the pointers to the startup script needed to tell OpenOCD what adapter I want to use. Note the "old_flash" entry which coaches me what to type to the telnet connection it then launches. Finally we have entries to launch gdb in two flavors, first the plain command line, and second using the "-tui" (text user interface) option. Using gdb presumes that I already have an OpenOCD process running, which I would start in another window by typing this:
openocd -f /usr/share/openocd/scripts/interface/stlink-v2.cfg -f /usr/share/openocd/scripts/target/stm32f1x.cfg

GDB, ARM, and Fedora

You will most likely be using OpenOCD on some kind of ARM target. Maybe not. If so, you will want the cross gdb known as:
arm-none-eabi-gdb
This used to be conveniently provided as a Fedora package (like all of the other parts of the ARM toolchain). Somewhere along the line this vanished. It is now (at least circa Fedora 39) available from a COPR (cool other projects repository), which is nice.

If you are using some other distribution, you may not have this headache, or maybe you will have worse headaches.

Debug adapters

This is some gadget with USB on one side and a JTAG connection on the other. I use a cheap ST-link v2 for my ARM microcontroller projects. I put "versaloon" into a blue pill board, and it seems to be a serviceable adapter for my Xilinx Zynq targets. I also have Segger j-link, and there are countless other commercial adapters. Betware of voltage issues. So far my systems at all 3.3 volt. My Segger claims to detect the target voltage (if you hook it up right). Some fancy adapters will offer ethernet rather than USB. The "black magic probe" essentially incorporates OpenOCD functionality within itself and allows you to connect gdb to it directly. Olimex makes lots of good stuff. Some of my fancier STM32 boards actually have a built in ST-link v3 adapter, and the latest versions of OpenOCD support v3 (which is definitely different than v2).

Tcl

Often pronounced (but never spelled) "tickle". This is a language which I deeply hate, but actually is rather suited for just the kind of use that OpenOCD puts it to. As a historical side note, the creators of Tcl had exactly this kind of use in mind and never intended it to be used as a general purpose programming language alongside things like Perl and Python. But that didn't stop people from using it in that way, and at one point in time it offered a seductively easy way to write GUI interfaces and the computing world was set back at least half a decade.

I will point out that chapter 23 of the OpenOCD manual is a "Tcl Crash course". So far my use of OpenOCD has not required me to work with Tcl, but I suppose the day is coming and the painful experiences of my past may be of benefit.

The OpenOCD manual tells us that it incorporates "Jim-Tcl" which is a small and stripped down version of the Tcl language. I am cool with all of this but ignoring it at the present time.

I'll also note in passing that Xilinx also uses Tcl as a "glue language" in much the same way as a part of many of their tools. So you have a choice between using their GUI interfaces or doing command line work and dealing with Tcl. Good to know and someday may be very useful.

Using OpenOCD with Versaloon and a Zynq based EBAZ-4205 board

Two notes up front, I abandoned Versaloon for my Segger clone (see the "hobos guide" part 2). Also (a note to myself) my files for this are in /u1/Projects/OpenOCD.

I connect my Versaloon adapter to the 14 pin JTAG connector on my EBAZ board, plug in the USB cable and then do this in one windows to start the OpenOCD server:

openocd -f versaloon.cfg
Open On-Chip Debugger 0.12.0
Then in another window, I do this:
telnet localhost 4444
Open On-Chip Debugger
> scan_chain
   TapName             Enabled  IdCode     Expected   IrLen IrCap IrMask
-- ------------------- -------- ---------- ---------- ----- ----- ------
 0 auto0.tap              Y     0x13722093 0x00000000     2 0x01  0x03
 1 auto1.tap              Y     0x4ba00477 0x00000000     2 0x01  0x03
This is Fedora 39 and I got OpenOCD from the standard fedora packages.
The startup script "versaloon.cfg" looks like this:
adapter driver vsllink
vsllink usb_vid 0x0483
vsllink usb_pid 0xA038
adapter speed 100
transport select jtag
Note that the speed is in kHz units, so this asks for an adapter speed of 100 kHz.
Indeed, when openOCD starts up, we see the message:
Info : clock speed 100 kHz

I originally thought this was 100 Hz and was deeply concerned. It may be possible to go fast once other clocks are set up. The guideline is that the JTAG clock can be 1/6 of the CPU clock (or less).

This all works as far as me typing the "scan_chain" command, but going further requires me to learn more, which is exactly why we are here.

Note that I could rename versaloon.cfg to openocd.cfg and as long as I start openocd in my project directory, I won't need any arguments to openocd.

Configuration files

My fedora install of openocd includes a bunch of files in /usr/share/openocd. The OpenOCD people have the idea of 3 sorts of files: interface, board, and target. So we see directories:
/usr/share/openocd/scripts/interface
/usr/share/openocd/scripts/board
/usr/share/openocd/scripts/target
In my case, I see:
/usr/share/openocd/scripts/interface/vsllink.cfg
/usr/share/openocd/scripts/board/digilent_zedboard.cfg
/usr/share/openocd/scripts/target/zynq_7000.cfg
I should probably take a look at these files, but for now I am just pressing on with my versaloon.cfg script.

I gave this a brief try, but it got all kinds of errors:

cp /usr/share/openocd/scripts/target/zynq_7000.cfg zynq.cfg
openocd -f versaloon.cfg -f zynq.cfg
Clearly I am getting ahead of myself.

JTAG and TAP

TAP stands for "test access ports" and the OpenOCD manual bluntly tells us that they are the core of JTAG.

Page 70 of the manual is "Autoprobing" and openOCD does this without you asking apparently when you launch it and at least get it using the correct adapter driver. And it spits out the result of autoprobing right in the mess of startup messages that you and I have been simply ignoring:

Info : clock speed 100 kHz
Warn : There are no enabled taps.  AUTO PROBING MIGHT NOT WORK!!
Info : JTAG tap: auto0.tap tap/device found: 0x13722093 (mfg: 0x049 (Xilinx), part: 0x3722, ver: 0x1)
Info : JTAG tap: auto1.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -irlen 2 -expected-id 0x13722093"
Warn : AUTO auto1.tap - use "jtag newtap auto1 tap -irlen 2 -expected-id 0x4ba00477"
Warn : gdb services need one or more targets defined
At least one useful bit of information is that "auto0.tap" is Xilinx, so it is probably the PL section of the Zynq (the FPGA). The other, "auto1.tap" is ARM, so that is probably the PS section of the Zynq (the dual core ARM).

So, I have tried playing with it, and now even after a power cycle of both the Ebaz and the versaloon I get:

Info : clock speed 100 kHz
Info : JTAG tap: auto1.tap tap/device found: 0x13722093 (mfg: 0x049 (Xilinx), part: 0x3722, ver: 0x1)
Warn : JTAG tap: auto1.tap       UNEXPECTED: 0x13722093 (mfg: 0x049 (Xilinx), part: 0x3722, ver: 0x1)
Error: JTAG tap: auto1.tap  expected 1 of 1: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Info : JTAG tap: auto0.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
No longer does it tell me there are no enabled taps. Perhaps there is a way to command a JTAG reset,

Reset

We have TRST (jtag TAP reset) as well as SRST (system reset). SRST should be just like pressing a reset button. I see TRST on my Ebaz board, but no SRST. It looks like Antminer boards have both SRST and TRST.

Note that Versaloon controls neither SRST or RRST, which is certainly a liability.


Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org