An introduction to STM32 microcontrollers

Today we will be looking at embedded hardware and developing programs for embedded hardware. An embedded system typically consists of a microcontroller connected to specialised hardware running a dedicated program with a dedicated set of functionality. Unlike the general-purpose hardware commonly found in desktops and laptops, where the programmer generally relies on the operating system to schedule tasks and abstract hardware through drivers, embedded hardware is much more bare metal. This means that as a programmer you have to have a really good understanding of the hardware, a basic understanding of electronics and how to use various debugging tools such as multimeters and oscilloscopes. In some cases, you may also have to design and prototype your very own circuit boards.

Embedded systems are actually much more prevalent than one might think, as we are surrounded by many different types of embedded systems. For instance, the LTE modems, WiFi chips, SSDs, hard drive controllers, etc. commonly found in mobile phones, laptops and desktops are forms of embedded systems. However, embedded systems can also be found in external form factors such as USB devices, or even external devices and appliances such as printers, alarm systens, microwaves, washing machines, and even cars.

While there are many different microcontrollers available that can be used to develop an embedded system, we will be focusing on STM32 hardware. One of the reasons is that depending on the vendor of the microcontroller, you might need a completely different set of libraries and tools to compile binaries, program the flash chip and debug the microcontroller. Furthermore, when just considering STM32 hardware, there is already a wide range of solutions available differing in terms of both performance and the features available. Finally, even the most basic chips such as the STM32F0 and STM32F1 will suffice for most as they are able to interface with I²C, SPI, USART, and in some cases even USB; and as they offer extensive support for general-purpose I/O.

Finding suitable hardware

Before we can get started, we first have to buy some hardware. In general, we are interested in a development board sporting a STM32 and depending on the development board we chose, we might also need a programmer in order to be able to program binaries to the flash chip and debug our code. While there is a jungle of options available, I will mostly focus on what I have experience with.

By far one of the easiest ways to get started, is by ordering a development board such as the STM32F0 Discovery. One of the benefits of using an actual development board is that a development board is actually targetted at developers. For instance, the STM32F0 Discovery allows you to program the board and debug your code directly using USB. Furthermore, the board exposes all the GPIOs using pin-out headers on both sides of the board allowing you to quickly prototype hardware designs using a breadboard and jump wires. Many more development boards can also be found at websites like Olimex.

For the more experienced among us, it is also possible to buy one of the ST-Link Programmer clones. While they are originally used as a programmer, some of these devices can also be repurposed by programming them. However, keep in mind that these devices are already made with a specific goal in mind which may be a limiting factor for your application.


In order to compile code into a suitable binary for our microcontroller, we first need a toolchain that targets ARMv6 and ARMv7-M. The easiest way to set up such a toolchain is to use the GNU ARM Embedded Toolchain. To install this toolchain on Linux Gentoo or Linux Funtoo, you can use the ebuilds from my overlay.

First create a file called /etc/portage/repos.conf/synkhronix.conf as follows:

location = /usr/local/overlay/synkhronix
sync-type = git
sync-uri =
auto-sync = yes

Next we fetch the overlay and update the eix database:

emerge --sync

Then we can install the GNU ARM Embedded Toolchain as follows:

emerge gcc-arm-embedded-bin

Once the toolchain has been installed, add the following line to your ~/.bashrc:

export PATH="$PATH:/opt/gcc-arm-embedded-bin/bin"


Once we can compile binaries for our microcontroller, we also need a tool to program the binary to the flash chip of the microcontroller. For this, we will be using OpenOCD:

emerge openocd


To simplify programming the STM32, we will be using libopencm3, an open-source firmware library for various ARM Cortex M microcontrollers including a wide variety of the STM32 microcontrollers. Our first Hello World program for the STM32 will be a program that repeatedly blinks the debugging LED. The example code can be found at and is based on libopencm3-examples:

git clone

Upon cloning the repository, we can build the code for our target device (e.g. the STM32F0 Discovery) as follows:

TARGET=stm32f0 make

Alternatively, the STM32F1 is also supported. Now that the miniblink program has been built, we can run OpenOCD in order to program our microcontroller:

TARGET=stm32f0 make openocd

Now open up another shell and run the following command to flash the microcontroller:

TARGET=stm32f0 make run-miniblink

If everything went well, the LED should now be blinking.