What does it take to turn a few lines of C into something a microcontroller can run? The answer involves more than a compiler: the program must be built for the right processor, placed in the chip’s memory, and transferred to the board before it can run.
A typical STM32 workflow
In an STM32 project, you usually start by choosing a chip or development board and deciding which pins and peripherals the application needs. You configure things such as GPIO pins and clocks, often with STM32CubeMX, then write your application code using ST’s device support or direct register access. Next you build the firmware with an Arm cross-compiler, flash it through a debug probe such as ST-LINK, and test or debug it on the board. You repeat that cycle as the application grows.
STM32CubeIDE can bring configuration, editing, building, flashing, and debugging into one place. That is convenient, but it can make the build feel like a single button press. Even when a tool generates the project, the same pieces still have to fit together: compiler settings for the chip, startup code, a memory layout, application and vendor sources, and a way to program the result.
Our approach
We’ll learn STM32 development by making the build process visible before relying on generated project files. Starting with a small CMake build, we’ll add the pieces firmware needs one at a time and see what each contributes. The goal is to understand the path from source code to a program that runs on a microcontroller, not to memorize a setup for one chip.
Once that foundation is in place, we’ll use ST’s device support and tools to build and flash a working LED blink. The goal is to understand the pieces well enough to investigate problems and recognize them in generated projects later.
Why learn the build?
A generated project can get you started quickly, but understanding its build gives you more control when you need to change it. You can see how source files, compiler settings, startup code, and the linker come together—and know where to look when a build fails or firmware doesn’t run as expected.
CMake also lets you run the build from a terminal, making it easier to repeat on another computer or in CI. We’re not replacing ST’s device support or arguing against CubeIDE: we’ll use the existing CMSIS and HAL code. The point is to understand how the tools fit together, so you can work confidently with both handwritten and generated projects.
What you’ll need
- A Nucleo board with an STM32L433RCT6P, plus a USB cable for its ST-LINK connection. If you use a different board, its LED pin and possibly other hardware details will differ.
- STM32CubeCLT for building and programming STM32 firmware from the command line.
- A terminal where the command-line tools are available on your
PATH.
STM32CubeCLT is ST’s command-line tool bundle for building and programming STM32 firmware without opening an IDE. It brings together the tools used in this course:
- CMake describes the project and configures the build.
- Ninja runs the build steps generated by CMake.
- Arm GNU toolchain (
arm-none-eabi-gcc) compiles and links firmware for the microcontroller. - STM32CubeProgrammer (
STM32_Programmer_CLI) transfers the finished firmware to the board.
Install STM32CubeCLT for your operating system and make sure its tools are on your PATH. On macOS or Linux, check with command -v cmake ninja arm-none-eabi-gcc STM32_Programmer_CLI. STM32CubeMX is a separate graphical configuration tool; you don’t need it for this series. You can build without a board connected; flashing and seeing the LED blink require the board.
From source code to running firmware
Building for an STM32 requires a cross-compiler: it produces code for the microcontroller’s processor and environment rather than an application for your computer. Writing the source is only the beginning. That source must become an image placed in the right memory, then reach the chip before it can run.
The path is compile → link → flash → run:
- Compile: Turn C and assembly source into object files containing code for the target microcontroller.
- Link: Combine those files and place code and data in the chip’s Flash and RAM. The result is an ELF file that also carries information useful for debugging.
- Flash: Transfer the firmware to the chip through a debug probe. A successful build on your computer does not program the board.
- Run: After reset, startup code prepares the application’s memory and calls
main(), where the application begins its work.
What’s next
You now have a map of how STM32 source code becomes running firmware—and why understanding the build is useful even when tools generate a project for you. In the next lesson, we’ll take the first practical step: tell CMake to use the Arm toolchain and compile a small C file for the microcontroller.