Flashing and debugging STM32 microcontrollers under Linux

One of my interests is electronics and microcontrollers, and since I mainly use Linux for developing I wanted to find a way to do programming and debugging for ARM microcontrollers, more specifically STM32 (STM32F4 Discovery, STM32F413 Nucleo and small boards like blue pill or red pill), which are the ones I use the most. And ideally using open source, non proprietary and packages already in my distro (Ubuntu 18.04).

The method below works out of the box for development cards with an onboard ST-LINK device like the Discovery and Nucleo boards; other minimalist boards like the blue/red pill will require an ST-LINK V2 dongle (that you can buy for a few dollars online) or you can flash your own if you already have a spare board – but not with this procedure, Il´ make another post on that.

Flashing the MCU

So, first thing is flashing. OpenOCD can do the job, however at the time of writing the Ubuntu package is not up to date with the latest sources, so many new boards (like the STM32F413 Nucleo) are not recognized. If this is your case you’ll have to install from sources (see below) and cross your fingers; otherwise you can use the distro’s package and skip the building process:

~$ sudo apt install openocd

Building OpenOCD

If your board is not recognized you can try with a newer version of Open OCD; uninstall the package shipped with Ubuntu, download the dependencies for building, download the sources and build:

~$ sudo apt remove openocd
~$ sudo apt build-dep openocd
~$ git clone https://git.code.sf.net/p/openocd/code openocd-code
~$ cd openocd-code
~$ ./bootstrap
~$ ./configure
~$ make
~$ sudo make install

If everything goes well you’ll have the lates and greates OpenOCD installed in /usr/local. You now need to make udev recognize the board, or you may have permission problems; create the file /etc/udev/rules.d/99-openocd.rules with the following content:

#STLink V2
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="664", GROUP="plugdev"

Finally refresh udev:

# udevadm control --reload-rules && udevadm trigger

Program the MCU

Now connect your board and run OpenOCD, specifying your board with the -f option; for my Nucleo board, for example:

~$ openocd -f "board/st_nucleo_f4.cfg"
Open On-Chip Debugger 0.10.0+dev-00632-g44009186 (2018-12-26-20:41)
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: 2000 kHz
adapter_nsrst_delay: 100
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 2000 kHz
Info : STLINK V2J28M17 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.247800
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : Listening on port 3333 for gdb connections

Now connect to the OpenOCD server (telnet localhost 4444) and upload the program with the following commands:

reset init
flash write_image erase myprogram.elf

If everything goes well the program will be flashed into the MCU; the output will be something like this:

~$ telnet localhost 4444
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> init
> reset init
Unable to match requested speed 2000 kHz, using 1800 kHz
Unable to match requested speed 2000 kHz, using 1800 kHz
adapter speed: 1800 kHz
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0xfffffffe msp: 0xfffffffc
Unable to match requested speed 8000 kHz, using 4000 kHz
Unable to match requested speed 8000 kHz, using 4000 kHz
adapter speed: 4000 kHz
> halt
> flash write_image erase src/arm/blinky/Debug/blinky.elf
auto erase enabled
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x20000044 msp: 0xfffffffc
wrote 16384 bytes from file src/arm/blinky/Debug/blinky.elf in 1.414823s (11.309 KiB/s)
> exit
Info : dropped 'telnet' connection

To debug, open another teminal and run arm-none-eabi-gdb, specifying the .elf of your program; then type the following:

$ arm-none-eabi-gdb myprogram.elf
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
(gdb) monitor reset halt
(gdb) load
Loading section .vectors, size 0x100 lma 0x20000000
Loading section .text, size 0x5a0 lma 0x20000100
Loading section .data, size 0x18 lma 0x200006a0
Start address 0x2000061c, load size 1720
Transfer rate: 22 KB/sec, 573 bytes/write.
(gdb) continue

That’s it, happy debugging!

Un commento su “Flashing and debugging STM32 microcontrollers under Linux”

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *