Skip to content

Using an STLink Dongle and GDB with your BlackIce II

Tom Verbeure edited this page Mar 24, 2018 · 4 revisions

Introduction

When you want to develop new code for the STM32 processor on your BlackIce board, you'll quickly want to use a debugger, GDB.

This page describes what you need and how to do this.

General Overview

Debugging on embedded systems follows the following plan:

  • On your PC, you run the debugger itself. This is almost always GDB.

    Note that you need to run a version of GDB that understands the CPU architecture of the embedded CPU. In our case, we're running the ARM version of GDB: arm-none-eabi-gdb.

    GDB doesn't know anything about how to connect to the target system. It translates highlevel user commands like setting breakpoints, stepping through code, etc into lower level commands that are still pretty high level (e.g. write this byte to that memory address on the embedded system.)

    These lower level commands must be interpreted by the so-called GDB server.

  • OpenOCD.

    This is the GDB server. It's a translater of the low level commands in two ways. It knows how to talk to a hardware debug dongle, like the STLink dongle, and it knows how to translate the low level commands for a particular CPU.

  • Hardware Debug Dongle

    This is the physical interface that connects your PC to your embedded system. Very often, it has a USB connector on one side, and a generic wire interface on the other, that can plug into the embedded hardware. (Instead of USB, a UART or Ethernet port is possible as well, but less common.)

The STLink v2 Dongle

The STM32 on the BlackIce board uses the ARM proprietary Single Wire Debug (SWD) protocol, which uses... two wires: SWCLK and SWDIO.

In order to drive them, you need an STLink v2 dongle. You can buy an original one (with some features that you don't need) from ST for around $20, or you can buy a much cheaper clone on the web. They are absolutely everywhere and go for as low as $1.80 on AliExpress (with 50 days of delivery time) or $6 on your local web retailer.

They look like this:

STLink v2 Dongle

OpenOCD

As mentioned before, OpenOCD is the glue that links GDB to the hardware dongle and the embedded CPU.

Compiling OpenOCD and Installing

New CPUs come out all the time, and the STM32L4xx is not very old, so you need a fairly recent version of OpenOCD.

It's best to just download the source code, and compile it.

git clone git://git.code.sf.net/p/openocd/code openocd
cd ./openocd
./configure --prefix=/usr/local
make
sudo make install

Note: you will probably need to install a bunch of libraries.

Running OpenOCD

Plug in your STLink dongle, and run the following command:

sudo openocd -f /usr/local/share/openocd/scripts/interface/stlink.cfg -f /usr/local/share/openocd/scripts/target/stm32l4x.cfg

You should see something like this:

Open On-Chip Debugger 0.10.0+dev-00362-g78a4405 (2018-03-22-05:41)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
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
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : clock speed 480 kHz
Info : STLINK v2 JTAG v17 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.229552
Error: init mode failed (unable to connect to the target)
in procedure 'init'
in procedure 'ocd_bouncer'

Ignore the error at the bottom: we haven't connected our STLink dongle to the BlackIce board yet! The important part is that OpenOCD is communicating correctly with the STLink dongle.

Connecting the STLink Dongle

You will see the pinout of the dongle connector printed on the dongle casing itself. And, usually, there'll be a cable included with 4 wires.

Connect them as follows:

  • SWDIO: from pin 2 on the dongle to pin 11 on the RPi connector of your board
  • SWCLK: from pin 6 on the dongle to pin 7 on the RPi connector
  • GND: from pin 4 on the dongle to pin 9 on the RPi connector
  • GND: from pin 3 on the dongle to pin 25 on the RPi connector

Do NOT connect the 3.3V or 5V pins. The STLink dongle is not strong enough to power the BlackIce board!

Power up the BlackIce-II Board

Use an additional USB cable and plug it into one of the USB ports of the BlackIce board.

Connecting to the STM32 through OpenOCD

With everything wired up, we can now restart openocd again. And if all goes well, you should see this:

ubuntu@ubuntu-xenial:~/projects/libopencm3-examples/examples/stm32/l4/other/usb_cdcacm$ sudo openocd -f /usr/local/share/openocd/scripts/interface/stlink.cfg -f /usr/local/share/openocd/scripts/target/stm32l4x.cfg
Open On-Chip Debugger 0.10.0+dev-00362-g78a4405 (2018-03-22-05:41)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
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
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : clock speed 480 kHz
Info : STLINK v2 JTAG v17 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.229552
Info : stm32l4x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : Listening on port 3333 for gdb connections

Success! The STM32 CPU has been successfully identified!

We don't have GDB running yet, but OpenOCD also has a console mode through which you can issue all kinds of management commands.

In a different terminal windows, so the following:

telnet localhost 4444

You should see this:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
>

There are tons of commands. You'll get a list of them if you type 'help'.

Reading and Writing the STM32 Flash through OpenOCD

Probably the most interesting part is the one where you can read and write to the flash memory of the STM32. That's right! You don't need to switch the DFU jumper on the BlackIce board anymore to access the flash.

Here's how you can dump the current contents of the flash:

> dump_image dump.bin 0x08000000 0x1ffff
dumped 131071 bytes in 3.969067s (32.249 KiB/s)

And here's now you could reflash the iceboot firmware:

First halt the CPU:

> reset halt
adapter speed: 500 kHz
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0800018c msp: 0x20010000

Then flash the binary:

> flash write_image erase /home/ubuntu/projects/BlackIce-II/firmware/iceboot/iceboot.raw 0x08000000
auto erase enabled
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x20000050 msp: 0x20010000
block write succeeded
wrote 40960 bytes from file /home/ubuntu/projects/BlackIce-II/firmware/iceboot/iceboot.raw in 3.677231s (10.878 KiB/s)
>

Connecting GDB to the STM32

Make sure that you have iceboot compiled, and flash it using the instructions above.

Now do the following:

cd ~/BlackIce-II/firmware/iceboot
arm-none-eabi-gdb -ex "target remote localhost:3333" ./output/iceboot.elf

OpenOCD is ready to accept low level GDB commands on port 3333, so we're telling GDB to connect to that. And GDB uses ELF files to learn the variables and functions that are compiled in your binary. So we specify that as well.

You will see something like this:

GNU gdb (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 8.0.50.20171128-git
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./output/iceboot.elf...done.
Remote debugging using localhost:3333
Reset_Handler () at ../Drivers/CMSIS/Device/ST/STM32L4xx/Source/Templates/gcc/startup_stm32l433xx.s:81
81  ldr   sp, =_estack    /*_estack Atollic update: set stack pointer */
(gdb)

Let's set a breakpoing at main:

(gdb) br main
Breakpoint 1 at 0x80012b4: file main.c, line 95.

And run the program:

(gdb) c
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 1, main () at main.c:95
95  HAL_Init();
(gdb)

There we have it! We've successfully taken over control of the controller. We can run program, set breakpoints and inspect variables!