Firmware 101: STM32 Quickstart guide

A ready-to-use tutorial to start with firmware development on STM32 board

Leonardo Cavagnis
8 min readOct 13, 2021

Hardware: the part of a computer that you can kick; Software: the one you can only curse at… Firmware: the part you can do both!”

A Firmware is a specific class of software that provides the low-level control for a specific hardware.
Examples of devices containing firmware are the embedded systems.
An embedded system is a computer system built for a specific purpose (typical examples are: robots, digital cameras, gaming consoles, home appliances, etc…).

Embedded System — application fields

Embedded systems are based on electronic boards where the main component is called MCU. MCU stands for MicroController Unit, it is the “brain” of the computer system and its main task is to perform the specific operations for which it was programmed (E.g., digital camera: taking and managing photos). The firmware is the program that performs the operations, and it is stored in MCU’s memory.

One of the most important MCU manufacturers is STMicroelectronics (ST).
ST produces a wide range of semiconductor electronic components. It offers a massive microcontroller product portfolio. ST MCUs are robust, low-cost, up to 32-bit ARM-based architecture and with a comprehensive choice of peripherals.

How do I know which MCU is the right one for my application?
MCUs differ on: memory size, computational power, type, quantity of peripherals and so on.
The best way to choose the correct MCU for your application is to test your program on different MCUs in order to evaluate performance and pitfalls.

MCU vendors produce an electronic boards called Evaluation Kit with the purpose to allow developers to “evaluate” their own application on a specific MCU.
In addition to MCU, EvalKits contain external circuitry, such as sensors, memory interfaces, displays and many more.
ST offers an extensive catalogue of evaluation kit boards.

The STM32 evaluation board

You will use the STM32F072B-DISCO Evaluation Board in this tutorial.

STM32F072B-DISCO Evaluation Board

This kit includes everything newbie and expert users require to quickly get started with firmware development. It is based on the STM32F072RBT6 MCU and it also includes a gyroscope, some LEDs, buttons, touch sensor and USB connectors.

STM32F072RBT6 is an ARM Cortex-M0 RISC mainstream microcontroller suitable for a wide range of applications. It belongs to STM32: a family of 32-bit MCU produced by ST. There are several sub-families in the STM32 family divided by performance and application field.
Below there is a comparison scheme.

Comparison between STM32 families

Led blinking: the “hello world” of Firmware

Any developer, to become familiar with a new programming language, starts with the “Hello world!” program.

Hello world!” is a simple program, frequently used for didactic purposes, which produces as a result the output “Hello world!” (or other variants) using standard output channels (e.g., console).

For a firmware developer, the standard output channels are the MCU’s outputs. A typical “Hello world!” program is a procedure which controls an output pin of a MCU to manage the brightness of a LED (aka “Led blinking” program).

In this project, you will manage all the LEDs mounted on the evaluation board (LD3, LD4, LD4 and LD5). The program will continuously turn on the LEDs in sequence.

Hardware block diagram of STM32F072B-DISCO
Led blinking demo

To start developing, you need an IDE to create your firmware application.
In particular, you will see two ways to achieve the same result:

  • STM32CubeIDE: An integrated development tool for STM32 microcontrollers.
  • STM32CubeMX + Keil µVision IDE:
    * Keil is a software development environment for Arm Cortex-M based microcontroller.
    * STM32CubeMX is an initialization code generator for STM32 microcontrollers.

STM32CubeIDE

STM32CubeIDE is an all-in-one software tool. It includes an Eclipse-based IDE and a code generator. After selecting the STM32 MCU used in your application, the tool will create and initialize the project by generating configuration code. Also with the same tool, you will build and run the application on the development board.

Development flow with STM32CubeIDE

Let’s dive in depth!

  • Open STM32CubeIDE Software.
STM32CubeIDE start-up page
  • Go to: File New… STM32 Project.
  • Click on Board Selector and select STM32F072B-DISCO in Commercial Part Number dropdown menu.
Board Selector page
  • Type a project name and verify that the Targeted Project Type is STM32Cube. In this way, you can leverage the STM32 code generator tool.
STM32 Project options
  • After creating the project, the Device Configuration Tool page will appear.
    It contains all the necessary features needed to configure the MCU.
    The IDE automatically configures the peripherals based on the discovery board selected during the project creation. You can see the 4 LEDs already initialized.
Device Configuration Tool
  • Open the main.c file under <project name>/Core/Src path.
  • In the first lines of the main function the code generator initializes the MCU and peripherals for you. These functions contain all the configurations selected in the Device Configuration Tool page.
int main(void) {  /* Reset peripherals, Initializes Flash interface and Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C2_Init();
MX_SPI2_Init();
MX_TSC_Init();
MX_USB_PCD_Init();
...}
  • To produce the desired LEDs behaviour, insert these lines of code in the while(1) { … } construct.
while(1) {  HAL_GPIO_WritePin(GPIOC, LD3_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, LD5_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, LD6_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, LD4_Pin, GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOC, LD3_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, LD5_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, LD6_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, LD4_Pin, GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOC, LD3_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, LD5_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, LD6_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, LD4_Pin, GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOC, LD3_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, LD5_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, LD6_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, LD4_Pin, GPIO_PIN_SET);
HAL_Delay(500);
}

The HAL_GPIO_WritePin(…) function changes the state of an output pin: state 0 (GPIO_PIN_RESET) or state 1 (GPIO_PIN_SET).
In STM32 MCU, every pin is identified with a port and a pin number:
* Red (LD3) — PC6 (Port C, pin #6)
* Green (LD5) — PC9 (Port C, pin #9)
* Blue (LD6) — PC7 (Port C, pin #7)
* Orange (LD4) — PC8 (Port C, pin #8)
For example, to turn on the green LED use:
HAL_GPIO_WritePin(GPIOC, LD5_Pin, GPIO_PIN_SET).

  • Now that the application is ready, you have to upload it on the board:
    * Connect discovery board to PC with the USB cable
    * STM32CubeIDE automatically detects the STM32 board
    * Right click on the project name:
    Run AsSTM32 Cortex-M C/C++ Application
    * Wait until the console shows Download verified successfully
STM32CubeIDE Console
  • Look at the board… LEDs are blinking as you expected!

STM32CubeMX + Keil uVision IDE

In this section you will follow a different approach to create the same firmware application.
Firstly, you generate initialization code using STM32CubeMX tool and then you build and run the project on the STM32 board with Keil uVision.
Keil uVision is a professional IDE where you can create projects for a wide range of ARM based MCU. STM32 is one of the many MCUs based on ARM architecture.

Development flow with SMT32CubeMX and Keil uVision IDE

Let’s start with the code generation phase!

  • Open STM32CubeMX Software.
STM32CubeMX start-up page
  • Go to: File New project…
  • In the Board Selector: choose STM32F072B-DISCO from the dropdown menu and click on Start Project.
Board Selector section
  • After project creation, the MCU default Pinout Configuration is shown (GUI is very similar to STM362CubeIDE).
  • In the Project Manager section, insert a Project Name, a Project Location (where your project will be generated) and select from the Toolchain/IDE dropdown menu the option: MDK-ARM (mandatory if you want to open the project with Keil).
Project manager section in STM32CubeMX
  • Click on the Generate Code button.
    Project will be generated in <project location>/MDK-ARM folder.

Now it is time to build and run the project with Keil!

  • Open Keil uVision software.
Keil uVision start-up page
  • Go to: Project → Open project… and select file with extension .uvprojx in <project location>/MDK-ARM folder.
  • main.c file is located in <project name>/Application/User/Core.
  • In while(1) { … } construct, insert the lines of code seen in the previous section to turn on LEDs in sequence.
  • Click on Build icon to create the program to upload on MCU.
  • Evaluation board is not automatically detected by Keil.
    So, before loading the program on the evaluation board, you need to setup Keil with the type of MCU you are using.
    * Go to: Flash → Configure Flash Tools…
    *
    In the Utilities section, click on the Settings button.
    * In the Flash Download section, click on Add and select the two items related to STM32F0xx MCU.
Keil uVision — Target Driver Setup
  • To load the program on the board, click on the Download icon.
Build and Download icons
  • Look at the board… magic is done!

Auto-generated code vs starting-from-scratch

Using auto-generated code on demo boards is the most rapid way to build a hands-on firmware project. This approach is suggested for newbies or for those who want to quickly create an embedded system prototype.

But dealing with auto-generated code can be difficult specially in situations where you want to customize the handling of a specific peripheral or/and using advanced features of an MCU.

In this case it is preferable to start from scratch avoiding the use of tools for code-generation. We will address this approach in a next article.

--

--

Leonardo Cavagnis

Passionate Embedded Software Engineer, IOT Enthusiast and Open source addicted. Proudly FW Dev @ Arduino