Compile OpenOCD from Sources

This chapter is based on

The compilation took place on a plain-vanilla “Debian GNU/Linux 9.6 (stretch)”.


Except for libusb-1.0-0-dev all packages are already installed.

make is already the newest version (4.1-9.1).
libtool is already the newest version (2.4.6-2).
pkg-config is already the newest version (0.29-4+b1).
autoconf is already the newest version (2.69-10).
automake is already the newest version (1:1.15-6).
texinfo is already the newest version (6.3.0.dfsg.1-1+b2).
libusb-1.0-0 is already the newest version (2:1.0.21-1).
libusb-1.0-0 set to manually installed.
The following NEW packages will be installed:
  libusb-1.0-0-dev libusb-1.0-doc

Retrieve the Sources

The sources are the current snapshot of the git archive. git clone git:// openocd yields:

Cloning into 'openocd'...
remote: Enumerating objects: 59586, done.
remote: Counting objects: 100% (59586/59586), done.
remote: Compressing objects: 100% (23697/23697), done.
remote: Total 59586 (delta 48907), reused 43359 (delta 35727)
Receiving objects: 100% (59586/59586), 13.64 MiB | 355.00 KiB/s, done.
Resolving deltas: 100% (48907/48907), done.

cd openocd followed by git pull proves that the sources are up-to-date:

Already up-to-date.

… More Sources

The remaining dependencies are downloaded by a script: ./bootstrap:

+ aclocal
+ libtoolize --automake --copy
+ autoconf
+ autoheader
+ automake --gnu --add-missing --copy installing './compile' installing './config.guess' installing './config.sub' installing './install-sh' installing './missing' warning: wildcard $(srcdir: non-POSIX variable name (probably a GNU make extension) installing './INSTALL' installing './depcomp' installing './mdate-sh' installing './texinfo.tex'
Setting up submodules
Submodule 'jimtcl' ( registered for path 'jimtcl'
Submodule 'src/jtag/drivers/libjaylink' ( registered for path 'src/jtag/drivers/libjaylink'
Submodule 'tools/git2cl' ( registered for path 'tools/git2cl'
Cloning into '/home/h/openocd/jimtcl'...
Cloning into '/home/h/openocd/src/jtag/drivers/libjaylink'...
Cloning into '/home/h/openocd/tools/git2cl'...
Submodule path 'jimtcl': checked out 'a9bf5975fd0f89974d689a2d9ebd0873c8d64787'
Submodule path 'src/jtag/drivers/libjaylink': checked out '8645845c1abebd004e991ba9a7f808f4fd0c608b'
Submodule path 'tools/git2cl': checked out '8373c9f74993e218a08819cbcdbab3f3564bbeba'
Generating build system...
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, 'build-aux'.
libtoolize: copying file 'build-aux/config.guess'
libtoolize: copying file 'build-aux/config.sub'
libtoolize: copying file 'build-aux/install-sh'
libtoolize: copying file 'build-aux/'
libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'm4'.
libtoolize: copying file 'm4/libtool.m4'
libtoolize: copying file 'm4/ltoptions.m4'
libtoolize: copying file 'm4/ltsugar.m4'
libtoolize: copying file 'm4/ltversion.m4'
libtoolize: copying file 'm4/lt~obsolete.m4' installing 'build-aux/ar-lib' installing 'build-aux/compile' installing 'build-aux/missing' installing './INSTALL'
libjaylink/ installing 'build-aux/depcomp'
Bootstrap complete. Quick build instructions:
./configure ....


The default configuration ./configure covers the required adapters:

checking for makeinfo... makeinfo
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes

libjaylink configuration summary:
 - Package version ................ 0.2.0-git-8645845
 - Library version ................ 0:0:0
 - Installation prefix ............ /usr/local
 - Building on .................... x86_64-pc-linux-gnu
 - Building for ................... x86_64-pc-linux-gnu

Enabled transports:
 - USB ............................ yes
 - TCP ............................ yes

OpenOCD configuration summary
MPSSE mode of FTDI based devices        yes (auto)
ST-Link JTAG Programmer                 yes (auto)
TI ICDI JTAG Programmer                 yes (auto)
Keil ULINK JTAG Programmer              yes (auto)
Altera USB-Blaster II Compatible        yes (auto)
Bitbang mode of FT232R based devices    yes (auto)
Versaloon-Link JTAG Programmer          yes (auto)
TI XDS110 Debug Probe                   yes (auto)
OSBDM (JTAG only) Programmer            yes (auto)
eStick/opendous JTAG Programmer         yes (auto)
Andes JTAG Programmer                   yes (auto)
USBProg JTAG Programmer                 no
Raisonance RLink JTAG Programmer        no
Olimex ARM-JTAG-EW Programmer           no
CMSIS-DAP Compliant Debugger            no
Cypress KitProg Programmer              no
Altera USB-Blaster Compatible           no
ASIX Presto Adapter                     no
OpenJTAG Adapter                        no
SEGGER J-Link Programmer                yes (auto)


time make

real    1m55.945s
user    1m27.988s
sys     0m6.088s


The installation goes to /usr/local and must thus be doe as root. make install:


Revision and Location

ST-Link/V3 support seems to be in the OpenOCD source code archive since 2018-10-09. The compiled revision openocd --version is:

Open On-Chip Debugger 0.10.0+dev-00634-gdb070eb8 (2018-12-30-23:05)
Licensed under GNU GPL v2
For bug reports, read

The recently compiled version is invoked because it is in /usr/local as can be seen by type openocd:

openocd is /usr/local/bin/openocd

ST-Link/V3 Support

The new version comes with all the configuration files. cat /usr/local/share/openocd/scripts/interface/stlink.cfg tells that there is indeed support for STLink/V3:

# STMicroelectronics ST-LINK/V1, ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 in-circuit
# debugger/programmer

interface hla
hla_layout stlink
hla_device_desc "ST-LINK"
hla_vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753

# Optionally specify the serial number of ST-LINK/V2 usb device.  ST-LINK/V2
# devices seem to have serial numbers with unreadable characters.  ST-LINK/V2
# firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial
# number reset issues.
# eg.
#hla_serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f"

Note that the last line in the configuration file is outdated. Serial numbers are no longer supplied a C-strings. They are now plain hex string and the example above should read #hla_serial "AABC6E065075FF551742193F".


The following is for the emacs IDE and the recent GNU toolchain.

Hardware connections

Follow the instruction in UM2243 Rev 2, “section 15.2 How to adapt an STM32L476 Nucleo-64 to power the MCU from the Arduino AREF pin” to cut off the on-board ST-Link/V2-1 from the MCU. But to use the USB-power, leave JP5 in U5V position.

ST-Link/V3, MB1440BNucleo-L476RGWire Color
SignalConnectorPinSignal ConnectorPin
T_VCCCN613V3 CN64 green
CLK/T_SWCLK 2PA14CN715blue
GND 3GND CN66 violet
DIO/T_SWDIO 4PA13CN713black

Connect the ST-Link/V3 (for the SWD signals) and the on-board ST-Link/V2-1 (for the power supply) with the computer. I’ll make a tiny board for that.

Update Configuration Files

The configuration files of the new OpenOCD differ from those of the AC6 distribution (“System Workbench for STM32 IDE”). Whereas the latter (e.g. /home/h/Ac6/SystemWorkbench/plugins/fr.ac6.mcu.debug_2.3.1.201811131241/resources/openocd/scripts/st_board/nucleo_l476rg.cfg) unconditionally used ST-Link/V2-1 by including “interface/stlink-v2-1.cfg” (now deprecated), the new revision of OpenOCD uses “interface/stlink.cfg” for all versions of ST-Links. /usr/local/share/openocd/scripts/board/st_nucleo_l4.cfg reads:

# Should work with all STM32L4 Nucleo Dev Boards.

source [find interface/stlink.cfg]

transport select hla_swd

source [find target/stm32l4x.cfg]

# use hardware reset
reset_config srst_only srst_nogate

The local (= in-project) configuration file for the new OpenOCD should therefore start with “source [find board/st_nucleo_l4.cfg]”. For a full working version of a configuration file, see below.

udev Rules

But before a non-root user can access the ST-Link/V3, the file “/etc/udev/rules.d/49-stlinkv3.rules” must be set up:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374f", MODE:="666", TAG+="uaccess", SYMLINK+="stlinkv3_%n"

The mode is set here to “0666” so that the wole world can access the ST-Link/V3.

Multiple ST-Links

To switch between the on-board ST-Link/V2-1 and the new ST-Link/V3, an ID for each device is required. This can be acquired by lsusb -d 0483: -v | egrep 'iSerial|iProduct| ID ':

Bus 001 Device 075: ID 0483:374f STMicroelectronics 
  iProduct                2 ST-LINK/V3
  iSerial                 3 004300403137510539383538
Bus 001 Device 072: ID 0483:374b STMicroelectronics ST-LINK/V2.1 (Nucleo-F103RB)
  iProduct                2 STM32 STLink
  iSerial                 3 066CFF323535474B43125623

or by ls -l /dev/serial/by-id:

total 0
lrwxrwxrwx 1 root root 13 Dec 31 11:24 usb-STMicroelectronics_ST-LINK_V3_004300403137510539383538-if02 -> ../../ttyACM1
lrwxrwxrwx 1 root root 13 Dec 31 02:20 usb-STMicroelectronics_STM32_STLink_066CFF323535474B43125623-if02 -> ../../ttyACM0

Select a Specific Interface: OpenOCD Configuration

Now, the IDs go into the local OpenOCD configuration. I addition to the serial numbers the port numbers must be set up:

For a Nucleo-L476RG, create the file “stm32l476rg_nucleo.cfg”:

# This is an NUCLEO-L476RG board with a single STM32L476RGTx chip

source [find board/st_nucleo_l4.cfg]

set WORKAREASIZE 0x18000

transport select "hla_swd"


# Enable debug when in low power modes

# Stop Watchdog counters when halt

# STlink Debug clock frequency
set CLOCK_FREQ 4000

# use hardware reset, connect under reset
# connect_assert_srst needed if low power mode application running (WFI...)
reset_config srst_only srst_nogate connect_assert_srst

# hla_serial "066CFF323535474B43125623"
# telnet_port 4444
# gdb_port 3333
# tcl_port 6666

# hla_serial "0672FF485457725187052924"
# telnet_port 4445
# gdb_port 3334
# tcl_port 6667

hla_serial "004300403137510539383538"
telnet_port 4446
gdb_port 3335
tcl_port 6668

Connect to the Target

Only the serial number of the ST-Link/V3 is uncommented. Therefore, the device is started up with openocd -f stm32l476rg_nucleo.cfg on a separate console (gdbserver-console):

Open On-Chip Debugger 0.10.0+dev-00634-gdb070eb8 (2018-12-30-23:05)
Licensed under GNU GPL v2
For bug reports, read
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 500 kHz
adapter_nsrst_delay: 100
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Warn : Transport "hla_swd" was already selected
srst_only separate srst_nogate srst_open_drain connect_assert_srst
Info : Listening on port 6668 for tcl connections
Info : Listening on port 4446 for telnet connections
Info : clock speed 500 kHz
Info : STLINK V3J1M1B1S1 (API v3) VID:PID 0483:374F
Info : Target voltage: 3.298805
Info : stm32l4x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : Listening on port 3335 for gdb connections

Connect to gdb

To link to the arm-none-eabi-gdb, enter M-x load-file. The loaded file contains:

;;; Load the file with “M-x load-file prep”
(setq gud-gdb-command-name "/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/arm-none-eabi-gdb -i=mi")

Then, from emacs M-x gdb yields:

Run gdb (like this): /opt/gcc-arm-none-eabi-8-2018-q4-major/bin/arm-none-eabi-gdb -i=mi main.elf

Connect to the target with target remote localhost:3335. The debugging window of emacs shows:

Remote debugging using localhost:3335
0x00000000 in ?? ()

and the gdb-server console displays:

Info : accepting 'gdb' connection on tcp/3335
Info : Halt timed out, wake up GDB.
Error: timed out while waiting for target halted

Info : device id = 0x10076415
Warn : STM32 flash size failed, probe inaccurate - assuming 1024k flash
Info : flash size = 1024kbytes
Warn : negative reply, retrying
Warn : negative reply, retrying

The current revision of OpenOCD seems to have some issues in finding out the flash size. But after some seconds it comes up with the right values.

Now everything is set up for flashing the program with load:

Loading section .isr_vector, size 0x188 lma 0x8000000
Loading section .text, size 0x1dd0 lma 0x8000188
Loading section .init_array, size 0x8 lma 0x8001f58
Loading section .fini_array, size 0x8 lma 0x8001f60
Start address 0x8001ea0, load size 8040
Transfer rate: 13 KB/sec, 2010 bytes/write.

Steping a single instruction n gives:

82    movs  r1, #0

And the code window of emacs reads:

   ldr   sp, =_estack    /* Atollic update: set stack pointer */

 /* Copy the data segment initializers from flash to SRAM */
☛  movs  r1, #0
   b     LoopCopyDataInit

Printing the stack pointer p $sp yields:

$1 = (void *) 0x20018000

Looks good! ☺