ST Nucleo F103RB works with OpenOCD 0.8.0

Posted on 2014/11/11


Full disclosure: I work at ST Microelectronics, but what I write here is purely my opinion and my work, conceived and conducted in my spare time.

ST Nucleo-F103RB

ST Nucleo-F103RB

The ST Nucleo boards are development platforms mounting an STM32 microcontroller, made for the same enthusiasts that are attracted to Arduino and the like. They have between 64KiB and 512KiB of embedded Flash, up to 128KiB of RAM, up to around 100MHz of clock, ARM Cortex-M 32bit processor, an integrated programmer/debug adapter called ST-Link, Arduino-compatible connectors as well as a breakout pins that export all STM32 I/O, and their price is around 10$. Their intended development platform is ARM mbed, that allows to write code and build programs online, using a quite simple API that abstracts away many details of the platform, making it easy to start, and easy to share code and experience with the mbed community.

I have my hands on a Nucleo F103RB, that mounts an STM32F103RB microcontroller, and I wanted to try it on my Linux box. The first thing I did was plugging it in. The unusual thing about the Nucleo boards is that they appear, at the USB interface, as three different devices:  a storage disk with its file system, a serial port and a debugging interface. This is how it appears:

$ dmesg
[ 1209.124022] usb 3-2: new full-speed USB device number 3 using uhci_hcd
[ 1209.296729] usb 3-2: New USB device found, idVendor=0483, idProduct=374b
[ 1209.296734] usb 3-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1209.296738] usb 3-2: Product: STM32 STLink
[ 1209.296741] usb 3-2: Manufacturer: STMicroelectronics
[ 1209.296744] usb 3-2: SerialNumber: 066EFF534951775087044835
[ 1210.582585] usb-storage 3-2:1.1: USB Mass Storage device detected
[ 1210.582770] scsi10 : usb-storage 3-2:1.1
[ 1210.582887] usbcore: registered new interface driver usb-storage
[ 1210.604091] cdc_acm 3-2:1.2: This device cannot do calls on its own. It is not a modem.
[ 1210.604113] cdc_acm 3-2:1.2: ttyACM0: USB ACM device
[ 1210.605778] usbcore: registered new interface driver cdc_acm
[ 1210.605781] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[ 1211.584633] scsi 10:0:0:0: Direct-Access MBED microcontroller 1.0 PQ: 0 ANSI: 2
[ 1211.585468] sd 10:0:0:0: Attached scsi generic sg3 type 0
[ 1211.590616] sd 10:0:0:0: [sdc] 304 512-byte logical blocks: (155 kB/152 KiB)
[ 1211.593610] sd 10:0:0:0: [sdc] Write Protect is off
[ 1211.593615] sd 10:0:0:0: [sdc] Mode Sense: 03 00 00 00
[ 1211.596613] sd 10:0:0:0: [sdc] No Caching mode page found
[ 1211.596618] sd 10:0:0:0: [sdc] Assuming drive cache: write through
[ 1211.621623] sdc:
[ 1211.638608] sd 10:0:0:0: [sdc] Attached SCSI removable disk

$ lsusb
Bus 003 Device 006: ID 0483:374b STMicroelectronics 

The debugging interface doesn’t seem to appear, but the serial is created as “/dev/ttyACM0” and the disk as a SCSI adapter in “/dev/sdc“. In order to upload and flash code into the microcontroller it is sufficient to copy the binary file into the storage, and ST-Link will flash it and delete the file. It’s very simple and works out of the box in Linux, except for the fact that in my Debian testing computer it asked me for root permission before mounting it, but I solved this issue later…

The mbed website suggests to update the board with the latest firmware, but the downloads offer a Windows EXE updater and a Windows DLL as a driver. A quick Internet search didn’t provide solutions so I decided to skip the update hoping it will work anyway.

(Trying to) connect with OpenOCD 0.7.0

I wanted to see if I could connect to the STM32 with OpenOCD (like I did with Olimex STM32P), so I tried to see how the platform is supported.

At a first glance it seems that the OpenOCD that I have installed (0.7.0) already contains some configurations for ST-Link and STM32F1x, which looks like what I need. The scripts are usually installed in “/usr/share/openocd/scripts/” directory, which is also the directory from where OpenOCD searches for its configuration files.

I tried the following command, that specifies ST-Link as the interface, and a generic stm32f1x as the target, showing some debug information (level 3):

$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x_stlink.cfg -d3

But OpenOCD did not find the board. By looking at ST-Link configuration file it’s clear that it expected Product ID 0x3748 but this board appears as 0x374b. To correct the PID to the one we saw earlier I ran:

$ openocd -f interface/stlink-v2.cfg -c "hla_vid_pid 0x0483 0x374b" -f target/stm32f1x_stlink.cfg -d3

But the configuration failed at “stlink_usb_open()“, and by a quick search it seems to fail because I did not have permission to open the device. Usually OpenOCD solves this issue by creating an udev rule file in “/lib/udev/rules.d/60-openocd-custom.rules” that gives the plugdev group the necessary permissions. I decided to create a new udev rule file called “/etc/udev/rules.d/60-openocd-custom.rules” with just the following content for ST-Link product:

ACTION!="add|change", GOTO="openocd_rules_end"
SUBSYSTEM!="usb|tty|hidraw", GOTO="openocd_rules_end"
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="664", GROUP="plugdev"

But running the same command OpenOCD complained with the following message:

Debug: 164 7 stlink_usb.c:1233 stlink_usb_open(): stlink_usb_open
Debug: 165 7 stlink_usb.c:1251 stlink_usb_open(): transport: 1 vid: 0x0483 pid: 0x374b
Error: 166 10 stlink_usb.c:1279 stlink_usb_open(): read version failed
Debug: 167 10 hla_layout.c:49 hl_layout_open(): failed
Debug: 168 10 command.c:631 run_command(): Command failed with error code -4
User : 169 10 command.c:669 command_run_line(): in procedure 'transport'
Debug: 170 10 command.c:631 run_command(): Command failed with error code -4
User : 171 10 command.c:669 command_run_line(): in procedure 'init'

It turns out ST-Link/V2 and ST-Link/V2-1 are different in the USB device enumeration, and the OpenOCD 0.7.0 version I was using did not have support for ST-Link/V2-1.

Connecting with OpenOCD 0.8.0

So I upgraded to OpenOCD 0.8.0 that, in its changelog, explicitly mentions ST-Link/V2-1. In fact it works!

$ openocd -f interface/stlink-v2-1.cfg -f target/stm32f1x_stlink.cfg
Open On-Chip Debugger 0.8.0 (2014-10-20-22:02)
Licensed under GNU GPL v2
For bug reports, read
Info : This adapter doesn't support configurable speed
Info : STLINK v2 JTAG v23 API v2 SWIM v6 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 3.264064
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints

As cleanup, I removed my udev rule file because OpenOCD already installs a new rule for this adapter. It seems to me that another effect of adding this rule is that Nucleo USB disk storage can be mounted without root permissions.

GDB debugging

I wanted to see if I could debug the device, so I prepared this OpenOCD configuration file that I called “gdb-pipe.cfg“:

gdb_port pipe
log_output openocd.log

$_TARGETNAME configure -event gdb-detach {
 echo "Debugger detaching: resuming execution."

The script uses a functionality that creates a communication pipe for GDB and writes the output to a file instead of standard output. The “detach” configuration is useful because when GDB disconnects from the target I want the program to continue, and not to stay halted.

Then I prepared a GDB script “attach.gdb” that contains:

target remote | openocd -f interface/stlink-v2-1.cfg -f target/stm32f1x_stlink.cfg -f gdb-pipe.cfg
monitor halt
monitor gdb_sync

The script runs OpenOCD and communicates with it through a pipe, then synchronizes with the running target and stays halted. I then connected to the STM32 with the GDB from the GCC ARM Embedded toolchain. Here is an example of a debugging session:

$ arm-none-eabi-gdb --command=attach.gdb
GNU gdb (GNU Tools for ARM Embedded Processors)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <>
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=i686-linux-gnu --target=arm-none-eabi".
For bug reporting instructions, please see:
Open On-Chip Debugger 0.8.0 (2014-10-20-22:02)
Licensed under GNU GPL v2
For bug reports, read
0x00000000 in ?? ()
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x81000000 pc: 0x0800288c msp: 0x20004ff0
stepi ignored. GDB will now fetch the register state from the target.

Program received signal SIGINT, Interrupt.
0x0800288c in ?? ()
(gdb) info registers 
r0 0x7a412 500754
r1 0x19b62cba 431369402
r2 0x40000824 1073743908
r3 0x2cbb 11451
r4 0xf4240 1000000
r5 0x19ae88a9 430868649
r6 0x20 32
r7 0x14 20
r8 0xdffd6fde -537038882
r9 0xbffbfeff -1074004225
r10 0x48c30094 1220739220
r11 0x88dd0a7c -1998779780
r12 0x40013400 1073820672
sp 0x20004ff0 0x20004ff0
lr 0x8002891 134228113
pc 0x800288c 0x800288c
xPSR 0x81000000 -2130706432
(gdb) continue
Program received signal SIGINT, Interrupt.
0x08002890 in ?? ()

Flashing a binary program

I wanted to see if I could also flash the binary with OpenOCD; it’s not a crucial functionality since the binary can also be flashed by copying it into the disk storage, but it’s a good indication that thing works well. I took a binary file created and compiled with mbed with the following procedure:

  1. Add platform ST Nucleo F103RB to mbed compiler
  2. Create new program from template Blinky LED Hello World
  3. Compile it and it will download the binary program.

The downloaded binary is called “Nucleo_blink_led_NUCLEO_F103RB.bin“, so I prepared the following OpenOCD script called “flash_blink.cfg“:

reset init
flash write_image erase Nucleo_blink_led_NUCLEO_F103RB.bin 0x08000000

The script writes the binary at the beginning of the flash; the address is taken from the STM32F1X user manual. Then I flashed the device successfully with the following command:

$ openocd -f interface/stlink-v2-1.cfg -f target/stm32f1x_stlink.cfg -f flash_blink.cfg
Open On-Chip Debugger 0.8.0 (2014-10-20-22:02)
Licensed under GNU GPL v2
For bug reports, read
Info : This adapter doesn't support configurable speed
Info : STLINK v2 JTAG v23 API v2 SWIM v6 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 3.267240
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000108 msp: 0x20005000
auto erase enabled
Info : device id = 0x20036410
Info : flash size = 128kbytes
target state: halted
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20005000
wrote 12288 bytes from file Nucleo_blink_led_NUCLEO_F103RB.bin in 0.957933s (12.527 KiB/s)
shutdown command invoked

After manually pressing the Reset button the user LED on the Nucleo board starts to blink as expected.


In conclusion, I found out that is pretty easy to use the new Nucleo boards (I assume the other boards are the same as mine) on Linux, with the exception of firmware upgrade . Next time I will try to write and compile some C program outside of mbed development environment and flash it on board, but I don’t foresee any problems since I already did something similar on an STM32 in a previous blog post.

Posted in: Embedded