Getting started using the STM32 platform

See this GitHub repo for the related code (and a copy of this post).

I have an Arch Max STM32F4 development board. Although it supports mbed I like to understand how things work...

The datasheet and reference manual have all the required low-level hardware info. This guide will get you started compiling C programs to directly twiddle with the stuff from the reference manual.

I experimented with two ways to get started on the board: CMSIS and libopencm3. I preferred libopencm3 and that's what I'm using now, but have included examples using both. The toolchain and debugging stuff is the same between the two.


On Arch Linux, just install the arm-none-eabi-gcc and arm-none-eabi-newlib packages. Most other distros probably offer similarly named packages.


An openocd config file is provided in the Arch Max git repo. Then running openocd -f Arch_Max/arch_max.cfg with the board connected to a USB port should pick it up and provide a GDB server on port 3333. I have to run OpenOCD as root as it needs access to the /dev/hidraw0 device node to communicate with the board.


Once OpenOCD is running and connected to the board via USB gdb can be connected and used to run and debug binaries.

arm-none-eabi-gdb -x load.gdb binary.elf

The gdb script load.gdb will connect to the OpenOCD gdb server, reset the board and load the elf file into memory. You can continue (c) at the GDB prompt to just run the program. For debugging you can set breakpoints etc before running too.



Both the libopencm3 and the CMSIS examples will produce a binary which when run on the Arch Max board will blink the LED next to the ethernet port (GPIO B3).

The Makefiles in both examples will link an elf executable file, which is suitable for debugging and loading via GDB (see above). A further objcopy -O binary step (also shown in the Makefiles) provides a file suitable for flashing onto the chip's flash memory (I think - I've not got around to actually trying this yet!).

Using libopencm3

The libopencm3 project provide an free software library which is in many ways similar to CMSIS, but I found it easier to get started with and it is what I use for projects now. Note that despite the name it also supports a large range of Cortex-M4 devices!

There is an awk script (libopencm3/scripts/gnlink.awk) which can generate the required C flags and linker script for a device, see example-libopencm3/Makefile for usage.

The generated linker script sets the executable entry point to reset_handler which can be found in libopencm3/lib/cm3/vector.c. This is pretty minimal:

Note that the clocks are left in their reset state. In the example I have set them up (using the rcc_clock_setup_hse_3v3 function) to run at 168MHz. The settings there are correct for the Arch Max (I hope!) as it has a high-speed external (hse) 8MHz oscillator.

Using the functions in libopencm3 to do simple things like toggling the GPIO is probably rather wasteful as they each incur a function call overhead. If you are worried about this then you can build the libopencm3 library and your binary with link-time optimisation (LTO), which will inline any small functions the compiler thinks is wise.


I found it very difficult to find the CMSIS code. It turns out the best way to get hold of it for a platform with mbed support (which is quite a lot, including the Arch Max) is to just grab the mbed source code from mbed-os GitHub repo. The repository contains lots of stuff for mbed and mbed-os, but the interesting CMSIS code is in the targets folder.

Each supported chip has a folder containing a chip-specific startup assembly file. For the Arch Max this is in mbed-os/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F407xG/device/TOOLCHAIN_GCC_ARM/startup_stm32f407xx.S This assembly file contains the entry point (Reset_Handler) and quite well documented with comments - it:

In the same folder as the startup .S file there should be a linker script (.ld) which should be passed to the linker with the -T option. This is also quite well commented.

An implementation of SystemInit for the Arch Max is provided (mbed-os/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F407xG/TARGET_ARCH_MAX/system_stm32f4xx.c) which sets up the system clock and various other bits and bobs. This implementation calls into the HAL library (sources for which can be found at mbed-os/targets/TARGET_STM/TARGET_STM32F4/device/). I have provided a chopped down version system_light.c which does not depend on the HAL library.

The mbed files for your board should have some clues as to what pins are connected to the odd LEDs etc. which are probably on your board. For the Arch Max that was in mbed-os/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F407xG/TARGET_ARCH_MAX/PinNames.h

The provided Makefile shows the compiler/linker options and include paths required.

See example in the example-cmsis folder (note you'll need that checkout of mbed-os - see the readme in the folder).

Good overview of CMSIS on the LPC devices

Very useful tutorial

Useful tutorial on making a blinky

Tutorial not really checked out yet

↩ Home