STM32 dev

Jump to: navigation, search


Notes on STM32 microcontrollers and on how to get them working in DIY projects.

/// this is a work in progress draft ///


All about software tools for STM32 dev. Development environments, compilers, debuggers, IDEs etc.

ARM toolchains

gcc-arm-embedded Toolchain

Install the GCC arm-none-eabi toolchain for your OS. On Arch Linux this can be done with the package manager:

$ sudo pacman -S arm-none-eabi-gcc arm-none-eabi-gdb arm-none-eabi-binutils arm-none-eabi-newlib

Alternatively, it can be built from scratch, to have all tools and their sources in one place.

$ cp gcc-arm-none-eabi-5_2-2015q4-20151219-src.tar.bz2 ~/toolchain
$ cd ~/toolchain
$ tar -xjf gcc-arm-none-eabi-5_2-2015q4-20151219-src.tar.bz2
$ cd ./gcc-arm-none-eabi-5_2-2015q4-20151219/src
$ find -name '*.tar.*' | xargs -I% tar -xf %
$ cd ..
$ ./ --skip_steps=mingw32
$ ./ --skip_steps=mingw32,manual

Note that those skip_steps options were required in my case.

Linaro Toolchain

The Linaro toolchain seems to be famous as well.

Install it with your package manager if available, or build it yourself:

devkitpro devkitARM toolchain

Another gcc variant:

Used in the homebrew scene for game consoles like the GP32, Nintendo (3)DS and GBA. It can apparently also be used for the STM32s as well! And generates probably more optimized binaries?

(On Arch it can be installed from the AUR: . But beware, the compiler, link, binutils have all the same name as the ones from the official GCC arm-none-eabi toolchain. So it's probably better to install it manually.)

STM32CubeMX on Linux

STM32CubeMX is a code generator for STM32 micros that can come in handy when you start a new project. It generates all the necessary init and HAL code, library and custom pin mux code for your specific MCU.

Unfortunately, it comes as a Windows EXE and ST doesn't mention that it actually is a Java application. Luckily it can be installed on Linux by hand (thanks to 5V Joe's great note there):

  • Download STM32CubeMX.
  • Install the application (tested in January 2016):
$ unzip SetupSTM32CubeMX-4.12.0.exe -d stm32cube
$ cd stm32cube
$ java -cp . com.izforge.izpack.installer.bootstrap.Installer
  • Run:
$ cd <install_dir>
$ unzip STM32CubeMX.exe
$ java -cp .

STM32CubeMX to Makefile

For whatever reason, STM32CubeMX does not export plain GCC/Makefiles along with the initialization code. But instead, it supports an unpopular IDE called SW4STM32, which is also based on free GNU tools. So after installing STM32CubeMX, these are the steps to get the GCC/Makefile project running:

  • Get this nice Python script by Baoshi to generate the Makefile for an exported SW4STM32 project:
$ git clone
$ cd CubeMX2Makefile
$ python2 <your_sw4stm32_prject_dir>
$ cd <your_sw4stm32_prject_dir>
  • Fix a tiny bug in the generated Makefile (tested in January 2016). More can be read here.
$ grep __weak Makefile 
C_DEFS = -D__weak="__attribute__\(\(weak\)\)" -D__packed="__attribute__\(\(__packed__\)\)" -DUSE_HAL_DRIVER -DSTM32F072xB
$ sed -i 's/\\(\\(weak\\)\\)/((weak))/g' Makefile 
$ sed -i 's/\\(\\(packed\\)\\)/((packed))/g' Makefile 
$ grep __weak Makefile 
C_DEFS = -D__weak="__attribute__((weak))" -D__packed="__attribute__\(\(__packed__\)\)" -DUSE_HAL_DRIVER -DSTM32F072xB
  • Then build the binary:
$ make
arm-none-eabi-size build/STM32F072RBT6.elf
   text	   data	    bss	    dec	    hex	filename
   4568	     12	   1572	   6152	   1808	build/STM32F072RBT6.elf
arm-none-eabi-objcopy -O ihex build/STM32F072RBT6.elf build/STM32F072RBT6.hex
arm-none-eabi-objcopy -O binary -S build/STM32F072RBT6.elf build/STM32F072RBT6.bin	


Install OpenOCD and STLINK. On Arch Linux:

sudo pacman -S stlink openocd

Now OpenOCD and (arm-none-eabi-)gdb can be used to program and debug the MCU. All discovery boards also come with an ST-LINK/V2 programmer right built in speaking over USB to the host and over JTAG/SWD to the target (note: only two pins are actually required for SWD debugging/flashing (SWDIO/SWCLK), but that for later (see also #Hardware)). STM32 Discovery Boards should show up in the lsusb list like that:

$ lsusb
Bus 003 Device 006: ID 0483:3748 STMicroelectronics ST-LINK/V2

OpenOCD can now act as a "middleman" between the ST-LINK programmer and the user. As a server on the host, to which you can connect with telnet and GDB.

To configure OpenOCD, put a configuration file called opencd.cfg into the project folder and start OpenOCD. While working on the project, let it run there in the foreground to see all the logs...

For the STM32 F072 Discovery board this should work, for example:

$ cd <project_directory>
$ echo "source [find board/stm32f0discovery.cfg]" > openocd.cfg
$ openocd
Open On-Chip Debugger 0.9.0 (2015-05-19-13:50)
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: 1000 kHz
adapter_nsrst_delay: 100
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v17 API v2 SWIM v0 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 2.896454
Info : stm32f0x.cpu: hardware has 4 breakpoints, 2 watchpoints

(Don't worry about those warnings about the wrong clock speed for now...)

In order to program the flash, connect to OpenOCD via telnet in another terminal:

$ telnet 4444
Connected to
Escape character is '^]'.
Open On-Chip Debugger
> reset halt
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0xc1000000 pc: 0x080014d0 msp: 0x20004000
> flash probe 0
device id = 0x20016448
flash size = 128kbytes
flash 'stm32f1x' found at 0x08000000
> flash write_image erase build/STM32F072RBT6.elf
auto erase enabled
target state: halted
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20004000
wrote 6144 bytes from file build/STM32F072RBT6.elf in 0.503961s (11.906 KiB/s)
> reset run
> exit
Connection closed by foreign host.

This should write the binary to the flash memory and start the program. Of course, all those steps can be automated further and integrated into an IDE, but that's for later...

To program the STM32F0Discovery board for example, this can be used to just flash the chip:

$ openocd -f board/stm32f0discovery.cfg -c "program build/STM32F072RBT6.elf verify reset exit" 

To program a custom board for example with the STM32F0x chip, a command like this can be used:

$ openocd -f interface/stlink-v2.cfg -f target/stm32f0x.cfg -c "program testSTM32F072_interrupt_test0.elf verify reset exit"

To make things more convenient, add a new target flash to the Makefile with this command, and you can simply run make flash.

The exported main.c from STM32CubeMX was only slightly modified to let the user LEDs flash and react to the user pushbutton:

* main.c *

#include "stm32f0xx_hal.h"

void SystemClock_Config(void);
static void MX_GPIO_Init(void);

int main(void)
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  /* Configure the system clock */

  /* Initialize all configured peripherals */

  while (1)
    uint32_t delay;
    if( HAL_GPIO_ReadPin( GPIOA, GPIO_PIN_0 ) == GPIO_PIN_SET )
      delay = 50;
      delay = 250;

    HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_9 );
    HAL_Delay( delay );
    HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_8 );
    HAL_Delay( delay );
    HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_7 );
    HAL_Delay( delay );
    HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_6 );
    HAL_Delay( delay );


/** System Clock Configuration
void SystemClock_Config(void)

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);



  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
void MX_GPIO_Init(void)

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */

  /*Configure GPIO pin : PA0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PC6 PC7 PC8 PC9 */
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);


( Note that pins -- among various other things -- can be customized in the CubeMX editor. Reexporting code to an existing project is straight forward, and can be done easily while the old Makefile keeps valid for minor changes... - However, STM32CubeMX looks still quite unfinished to me. It's a nice concept, but where are all the ST libraries, for example for the touch functionality? It still needs to be downloaded separately... and it comes in a bloody EXE file as well! *arghs*

Unfortunately, things seem to be a bit confusing. If you're using a STM32F0, then probably need to take a look into the STM32CubeF0 software bundle, which contains a more up-to-date TouchSensing Library... Hm.

Also, note that most of the provided code by ST is only documented in the source files themselves... And there are at least two vastly differing versions of the basic functions out there, what makes copy/pasting/sharing a bit difficult. I even don't know if they continue working on this code base, or if they switch over to mbed. That seems to be the focus of those newer Nucleo evaluation boards. )

Debugging: GDB

GDB can be used to debug the code right on the hardware. While OpenOCD is running, you can connect to the target like this and step through the program:

$ arm-none-eabi-gdb -tui build/STM32F072RBT6.elf
Reading symbols from build/STM32F072RBT6.elf...done.

(gdb) target remote :3333
Remote debugging using :3333
Python Exception <type 'exceptions.NameError'> Installation error: gdb.execute_u
nwinders function is missing:
HAL_GetTick () at Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal.c:298

(gdb) c

Program received signal SIGINT, Interrupt.
0x080002f6 in HAL_Delay (Python Exception <type 'exceptions.NameError'> Installa
tion error: gdb.execute_unwinders function is missing:
    at Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal.c:317

(gdb) break main.c:91
Breakpoint 1 at 0x8001392: file Src/main.c, line 91.

(gdb) c
Note: automatically using hardware breakpoints for read-only addresses.
Python Exception <type 'exceptions.NameError'> Installation error: gdb.execute_u
nwinders function is missing:

Breakpoint 1, main () at Src/main.c:91

(gdb) detach
(qdb) quit

(Note: the -tui option is really great to inspect the code... see GDB Text User Interface)

IDE: Eclipse SW4STM32

GOOD NEWS: This officially supported Eclipse variant should work out of the box with STM32CubeMX generated project. You simply need to register on that site, and you'll get a software package that should work:

SW4STM32 - System Workbench for STM32: free IDE on Windows, Linux and OS X

(Side note: I don't know how well it works when you have another Eclipse installed on your system... currently testing this out.)

IDE: Eclipse with GNU ARM Eclipse plugin

To use Eclipse as an IDE for the STM32s, just install Eclipse and a the GNU ARM Eclipse Plugin.

  • Eclipse IDE for C/C++ (CDT). This can be installed manually or with your package manager.
  • Eclipse Plugin: GNU ARM Eclipse. - This can be done in the Eclipse Marketplace (under Help > Eclipse Marketplace (use the default options)).
  • Create a new Eclipse project with the GNU ARM Eclipse (Choose STM32Fxxx C/C++ Project in the Wizard)

With some minor adjustments in the settings (OpenOCD), the basic Blinky example that comes with the plugin should work out of the box, with a STLink v2 programmer. Code completion etc. works fine too.

(/todo: show every step)

But there's quite annoying problem with this workflow!:

Unfortunately, the plug-in author has updated just the template for STM32-F4 family to the more recently STM32Cube-F4 HAL framework from ST (which still supports only commercial IDE.....), leaving the other templates still based on the old Standard Peripheral Library, which is no longer supported by ST and STM32CubeMX tool used in my tutorial. This causes my instructions to be wrong for processor families different from STM32-F4.

So, several manual setup steps will be required to get started with your own STM32 project. To goal is to configure the project in STM32CubeMX, and use up-to-date HAL code, and not the deprecated Standard Peripheral Library.

The GNU ARM Eclipse plugin is great, but doesn't create projects with up-to-date code. So we need to modify the manually created GNU ARM Eclipse project. - I used a custom STM32F072C8 board, and all steps below assum this hardware. The steps would be slightly different for other hardware.

(This tutorial was helping here...)

  • First create a new 'C Project' in your Eclipse workspace.
  • In Wizard slide C Project: Choose Executable > Hello World ARM Cortex-M C/C++ Project and give it a name (e.g. testSTM32_00). This will generate a generic ARM project instead of an STM32Fxxx one. - Then hit Next.
  • In Wizard slide Target processor settings: Configure the target processor: For the STM32F072C8: Change the defaults to Flash size (kB): 64, RAM size (kB): 16, Use system calls: Freestanding (no POSIX system calls), Trace output: None (no trace output). - Then hit Next.
  • In Wizard slide Folders: Change Vendor CMSIS name to stm32f0xx. - Then hit next.
  • In Wizard slide Select Configurations: Leave as is. - Then hit Next.
  • In Wizard slide Cross GNU ARM Toolchain: Select GNU Tools for ARM Embedded Processors (arm-none-eabi-gcc) and either choose the global, system wide toolchain (probably in /usr/bin) or enter the path to your custom one. - Then hit Finish.

This will create a generic ARM project, which should build without errors (hit Ctrl+B).

Next, we need to add the vendor specific HAL code by ST generated with STM32CubeMX and/or downloaded in a more specific firmware package (STM32CubeF0, STM32CubeF4 etc.).

... So, after configuring a generic Eclipse project, we're ready to modify it.

  • Configure and export an EWARM project in STM32CubeMX (with default settings).

As a starting point, here's a bash script, that modifies the previously created Eclipse project:

#!/usr/bin/env bash

set -e

#echo "Press CTRL+C to proceed."
#trap "pkill -f 'sleep 1h'" INT
#trap "set +x ; sleep 1h ; set -x" DEBUG


echo --------------------------------------------------------------------------------
echo Eclipse Project Initializer for STM32F072 Dev
echo --------------------------------------------------------------------------------

echo The script is using the following paths:
echo Eclipse Project:
echo STM32Cube:
echo $STM32CUBEF0
echo STM32CubeMX:

echo -n "Do you want to proceed? [ENTER]"

echo Deleting files from eclipse project:
rm -fv $ECLIPSE_PROJECT/src/main.c
rm -fv $ECLIPSE_PROJECT/src/Timer.c
rm -fv $ECLIPSE_PROJECT/include/Timer.h

rm -fv $ECLIPSE_PROJECT/system/include/cmsis/stm32f0xx.h
rm -fv $ECLIPSE_PROJECT/system/include/cmsis/system_stm32f0xx.h

rm -fv $ECLIPSE_PROJECT/system/src/cmsis/system_stm32f0xx.c
rm -fv $ECLIPSE_PROJECT/system/src/cmsis/vectors_stm32f0xx.c

echo Copying: ST HAL:
cp -rfv $STM32CUBEF0/Drivers/STM32F0xx_HAL_Driver/Src/* \

cp -rfv $STM32CUBEF0/Drivers/STM32F0xx_HAL_Driver/Inc/* \

cp -rfv $STM32CUBEF0/Drivers/CMSIS/Device/ST/STM32F0xx/Include/* \

cp -fv $STM32CUBEF0/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/gcc/startup_stm32f072xb.s \

cp -fv $STM32CUBEF0/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/system_stm32f0xx.c \

# echo Copying: example project from STM32CubeF0:
#cp $STM32CUBEF0/Projects/STM32F072B-Discovery/Examples/GPIO/GPIO_IOToggle/Inc/* \

#cp $STM32CUBEF0/Projects/STM32F072B-Discovery/Examples/GPIO/GPIO_IOToggle/Src/main.c \

#cp $STM32CUBEF0/Projects/STM32F072B-Discovery/Examples/GPIO/GPIO_IOToggle/Src/stm32f0xx_it.c \

echo Copying: example project from STM32CubeMX:

echo Modifiying/fixing the memory map:
echo $ECLIPSE_PROJECT/ldscripts/mem.ld
sed -i 's/FLASH (rx) : ORIGIN = 0x00000000/FLASH (rx) : ORIGIN = 0x08000000/g' $ECLIPSE_PROJECT/ldscripts/mem.ld


echo Now, exclude the following file from the Eclipse project manually:
ls $ECLIPSE_PROJECT/system/src/stm32f0xx/stm32f0xx_hal_msp_template.c

echo And add the following preprocessor constants to the C/C++ compiler settings in Eclipse:
echo STM32F072xB

echo "And add the following config options to the GDB OpenOCD Debugging settings (in Run Configurations):"
echo "-f interface/stlink-v2.cfg -f target/stm32f0x.cfg"

This script needs to be modified according to your needs! (Currently is working for the STM32F072C8, and contains fixed paths! - Note that there minor inconsistencies in some of these ST projects. For example, all the provided STM32F072xB* files by ST work for both types of chips -- STM32F072x8 and STM32F072xB.)

Like described in the script above, some minor manual changes need to be made in Eclipse after running the script.

This should now be a good basis to start a new STM32 project.

Note that the GNU ARM Eclipse plugin always generates a Makefile for every project configuration (Debug / Release). It can be found in <project_folder>/Debug pr <project_folder>/Release respectively.


What is semihosting?

Semihosting is a mechanism that enables code running on an ARM target to communicate and use the Input/Output facilities on a host computer that is running a debugger.

Examples of these facilities include keyboard input, screen output, and disk I/O.

The GNU ARM Eclipse plugin comes with a really bare-bone implementation of some semihosting print functions that can be used to print logs to the console right in Eclipse (over GDB, without using any additional serial/UART connection whatsoever).

Since I'd always create a project without Semihosting enabled in the GNU ARM Eclipse wizard, you can still easily enable it later on:

The easiest way I've found so far, is by defining those Preprocessor constants in the C/C++ Project settings (Projects > Properties > C/C++ Build > Settings > Cross ARM GNU C/C++ Compiler > Preprocessor):


And then, by using the following function calls in your code to log stuff to the Eclipse console right away:

trace_initialize(); // in fact not required
// (...)
static int i = 0;
trace_puts( "hello" );
trace_printf( "nr %d\n", i++ );
HAL_Delay( 1000 );  

These functions were implemented by the author of GNU ARM Eclipse Liviu Ionescu, and can be looked up in these files:

  • <eclipse_project>/system/include/arm/semihosting.h
  • <eclipse_project>/system/include/diag/Trace.h
  • <eclipse_project>/system/src/diag/Trace.c
  • <eclipse_project>/system/src/diag/trace_impl.c

An interesting comment in trace_impl.c:133 says:

// Semihosting is the other output channel that can be used for the trace
// messages. It comes in two flavours: STDOUT and DEBUG. The STDOUT channel
// is the equivalent of the stdout in POSIX and in most cases it is forwarded
// to the GDB server stdout stream. The debug channel is a separate
// channel. STDOUT is buffered, so nothing is displayed until a \n;
// DEBUG is not buffered, but can be slow.
// Choosing between semihosting stdout and debug depends on the capabilities
// of your GDB server, and also on specific needs. It is recommended to test
// DEBUG first, and if too slow, try STDOUT.

Note that semihosting needs to be enabled in your Eclipse run configuration (it is by default), in the Startup tab > Enable ARM semihosting. This will tell GDB to use semihosting. Without enabling, calls to those trace_* functions will throw some kind of exception... and make the processor halt. I couldn't find out much yet about how this feature really works, somehow it uses a special BKPT instruction...

Semihosting (OS_USE_TRACE_SEMIHOSTING_STDOUT) can also be used in "Release" builds, since the semihosted calls don't rely on debug symbols.

IDE: Code::Blocks

My favorite cross-platform IDE for C/C++ is Code::Blocks. - And luckily, it also works well for ARM development! After twiddling around with those confusing Eclipse settings, I've almost forgot to try out and setup Code::Blocks.

The steps required are bit unintuitive, but building and debugging projects with full auto-complete and indexer support works now.

The advantages over using Eclipse:

  • Faster GUI.
  • Works with STM32CubeMX generated code.
  • Uses just a plain/manually editable Makefile to build the project.
  • Familiar C/C++ settings and more *transparent* project handling -> Edit + debug. Nothing more. Everything can be done by hand on a console too. No mysterious hidden helpers...

I'm still evaluating this workflow... But to get things up and running, you can do this:

(Assuming you already have a working Makefile based project, e.g. created with STM32CubeMX, like described above).

  • Open Code::Blocks and create an empty project (File > New > Project > Empty project).
  • Give it a name in the Wizard, and choose the GNU GCC Compiler for ARM, and save it.
  • Copy all content of the Makefile project over to Code::Blocks project folder.
  • Import all required source files into the Code::Blocks workspace (right click -> Add files recursively...).
  • Check Project > Properties > Project settings > Makefile: This is a custom Makefile.
  • Adjust the build settings in Project > Build options > "Make commands". - This might either require you to change the Makefile (i.e. add Debug/Release targets), or the commands. - For simplicity's sake, just ignore those $make, $makefile variables and overwrite them with your actual commands (i.e.$make -f $makefile $target -> make all).
  • Build the project and check in the Build log if there where any errors/warnings.

So, if this is working now, try to edit a source file and see if those really useful auto-complete and jump to declaration/implementation features are working. - One caveat of using an external Makefile is that the IDE doesn't know the current settings. So, for example, #defines are not available, and syntax highlighting will not update automatically... So it might be worth it add settings manually at some point.

Now, to get the flashing and debugging working, try this:

  • Go to the Settings > Debugger Settings.
  • Add a new GDB debugger setting (hit Create Config and call it ARM OpenOCD for example).
  • Change the Executable path according to your toolchains location, and check 'Do *not* run the debugee'.
  • Go to Projects > Properties > Debugger.
    • Change the <Project> Remote connection settings to IP: / Port: 3333.
    • Go to the <Project> Additional GDB commands tab. And enter those commands into the After connection box (change filename!):
monitor halt
load ./build/test.elf
file ./build/test.elf
monitor sleep 1000
monitor reset

To not run the program automatically, remove the last two commands. Then you need to Start / Continue the program twice, but you'll catch the first breakpoint you've set!

  • Choose Debug > Active Debuggers > GDB/CDB Debugger: ARM OpenOCD.
  • Start OpenOCD in a terminal. (Described above).
  • Start debugging by pressing the red arrow (Run / continue) in the debugging toolbar.

The steps are the same as the ones in this tutorial with screenshots.


stlink is a command line tool for programming, inspecting and debugging the STM32 microcontrollers. It also used internally by OpenOCD (I think). - It comes with several small programs (st-flash, st-info, st-term, st-util) that can come in handy while working with the STM32 micros.

There's a tutorial:

Some useful things I've discovered:

Just run st-util can Ctrl-C again to see all relevant uC properties:

$ st-util
2016-01-29T13:06:25 INFO src/stlink-common.c: Loading device parameters....
2016-01-29T13:06:25 INFO src/stlink-common.c: Device connected is: F07x device, id 0x20016448
2016-01-29T13:06:25 INFO src/stlink-common.c: SRAM size: 0x4000 bytes (16 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 2048 bytes
2016-01-29T13:06:25 INFO gdbserver/gdb-server.c: Chip ID is 00000448, Core ID is  0bb11477.
2016-01-29T13:06:25 INFO gdbserver/gdb-server.c: Target voltage is 3554 mV.
2016-01-29T13:06:25 INFO gdbserver/gdb-server.c: Listening at *:4242...

Or with st-info:

$ st-info 
st-info --flash
st-info --sram
st-info --descr
st-info --pagesize
st-info --chipid
$ st-info --flash
$ st-info --sram
$ st-info --descr
F07x device
$ st-info --pagesize
$ st-info --chipid

$ echo `st-info --sram | xargs -I@ printf "%d/1024\n" @ | bc`kB RAM
16kB RAM
$ echo `st-info --flash | xargs -I@ printf "%d/1024\n" @ | bc`kB FLASH

$ for a in sram flash pagesize; do echo `st-info --$a | xargs -I@ printf "%d/1024\n" @ | bc`kb $a; done
16kb sram
64kb flash
2kb pagesize

Or simply:

$ st-info --probe
Found 1 stlink programmers
 serial: 303030303030303030303031
openocd: "\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x31"
  flash: 131072 (pagesize: 256)
   sram: 16384
 chipid: 0x0416
  descr: L1 Med-density device




Projects / Demos / Code





All about hardware and hardware tools for STM32 dev. Chips, programmers etc.

ST-Link V2 Programmer

There are two popular ST-Link V2 Progammers on the market. They have a different pinout but work both well like described above.

ST-LinkV2 pinout 01.jpg

Alternatively, STM32Discovery/Nucleo boards too can be used as SWD programmers.

Luckily, only 4 pins have to be used to program and debug the target! To find out more about this protocol, have a look into Serial Debug Wire (SWD) as an alternative to JTAG.

Connect to following pins of the programmer to the corresponding pins on the PCB:

  • V3V
  • GND

-> NRST can be important too on some STM32 chips!

Remember: These are not the official ST-Link V2 Programmers, sold by ST.


STM32 based projects.


STM32basic is a test board to see how STM32 chips can be used in DIY circuits.

STM32basic rev0.01

An initial list of tests:

  • JTAG: See how we can program the thing. Do we need all JTAG pins? Or only the SWD pins? What about reset? - Do the cheapo Chinese STLink V2 programmer really work?
  • Basic I/O: LED and push button.
  • U(S)ART: Check whether it's possible to hook up an FTDI to send/receive characters to/from the STM32basic?
  • BOOT0/1: What about those boot modes?
  • Power Usage : 3V3 Regulator: ..

STM32basic pcb1b.jpg

Board at OSH Park:

KiCad project and everything else:
Remark: this has been made in hurry and is just a test:


So far, the tests have been working ok.

  • STLink V2 programmers seem to work fine, and only require 2 pins + VCC/GND! SWDIO and SWCLK, that's it! For programming and on-chip debugging.
  • I/O works as well. External interrupts can be configured.
  • UART works, but I have not yet tested it with a proper code. It was working with some echo snippet I've found somewhere.
  • Power usage is low. ~15 mA at 3.3 V.
  • BOOT0 jumper has to be set (connected to ground) in order to run code... - Other boot modes have not been tested yet. More tests are needed there... What are the other available boot modes, what about those built-in boot loaders?

However, the board has several flaws:

  • 1.27 mm pin-pitch headers cannot be arranged like that (GPIOs). They need to be further apart to make sockets/headers fit.
  • 3V3 LDO doesn't make much sense like this. Add add a buck/boost converter. Also remove 5V label.
  • This BOOT0 jumper isn't nice like this...
  • Remove unnecessary JTAG pins. SWD only.
  • Remove unnecessary USART pins.
  • Add crystal.
  • Add USB plug.

Probably, this will not be remade, since it was enough for a test. I'd like to make a very basic USB touch device next.

STM32basic Eclipse project

Test project to see if GPIOs with External interrupts and semi hosting works. Sloppy and not cleaned up yet...

Note: Eclipse projects can be imported in an existing or new workspace with: File > Import > General > Existing Projects into Workspace.