Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 5

Flashing Firmware with ST-Link

Recommended resources

Hello! Welcome to the fifth lesson in your journey to becoming a professional Embedded Systems Engineer.

In our last session, you wrote a complete bare-metal C program to control the onboard LED of your Blue Pill board. You now have a main.c file that contains all the logic for direct register manipulation. However, this code exists only on your computer. To bring it to life, we need to transfer it to the microcontroller.

Today's lesson addresses the crucial step of bridging the gap between software and hardware. We will focus on this learning outcome: Compile firmware and flash it to the target using ST-Link.

You will learn how to:

  1. Set up a project in STM32CubeIDE to house your bare-metal code.
  2. Compile your C code into a machine-readable executable file.
  3. Flash (or "program") that executable file onto your STM32's memory using the ST-Link debugger.

By the end of this lesson, you will see the LED on your board blinking, running the exact code you wrote.

1. The Toolchain: From C Code to Executable

The main.c file you wrote is human-readable source code. The STM32 microcontroller's ARM Cortex-M3 processor cannot understand it directly. It only understands machine code—a series of binary instructions.

The process of converting your C code into machine code is handled by a set of tools called a toolchain. For ARM-based microcontrollers, the most common open-source toolchain is GCC for Arm Embedded Processors. It includes:

  • Compiler (arm-none-eabi-gcc): Translates C/C++ files into assembly and then into object files (.o).
  • Linker (arm-none-eabi-ld): Combines your object files with library code and a linker script (which we'll cover later) to create a single executable file. The standard format is ELF (Executable and Linkable Format), which contains your code, data, and metadata for debugging.
  • Other utilities: Tools to convert the ELF file into simpler formats like raw binary (.bin) or Intel Hex (.hex) for programming.

Fortunately, STM32CubeIDE integrates this entire toolchain. When you "build" your project, the IDE automatically runs these tools in the correct sequence.


2. Setting Up the Project and Compiling the Firmware

While our previous lesson focused on writing code in a simple text editor to understand the fundamentals, a real project requires a proper structure. We'll now create a project in STM32CubeIDE and use it to compile our bare-metal blinky code.

The following video provides an excellent end-to-end demonstration. We will follow its steps for creating a project, compiling, and flashing.

11. Install STM32 CubeIDE and LED blink program for Windows (OpenOCD included)

Watch this video from MicroPeta by Nizar Mohideen. It walks through the entire process of setting up a project, connecting the hardware, compiling the code, and flashing it to the Blue Pill. Pay close attention to the settings he uses, as they are very reliable for clone boards.

Please watch the following segments: Hardware Connection: Starting just before the one-minute mark, first, ensure your ST-Link is connected to your Blue Pill exactly as shown. The four pins are 3.3V, GND, SWCLK, and SWDIO. Project Creation: About eight minutes into the video, follow these steps to create a new project. Select your MCU (STM32F103C8), name the project, and importantly, enable the debug interface by going to System Core > SYS and setting Debug to Serial Wire. Compiling: At the 15-and-a-half-minute mark, the video will show you how to compile the project using the 'hammer' icon. This is the 'Build' step.

Your Task: Compile Your Bare-Metal Code

  1. Create a New Project: Following the video's guidance, create a new STM32 project for the STM32F103C8T6. Name it something like BareMetal_Blinky.
  2. Enable Serial Wire Debug: This is a critical step. In the .ioc configuration file that opens, go to System Core -> SYS -> Debug and select Serial Wire. This configures the pins needed for the ST-Link to communicate with the chip.
  3. Save and Generate Code: Save the .ioc file (Ctrl+S). The IDE will generate a project structure with a main.c file.
  4. Replace main.c: Open the main.c file located in the Core/Src folder of your project. Delete all the auto-generated content. Now, copy and paste the complete bare-metal code you created in the previous lesson into this empty main.c file.
  5. Compile (Build) the Project: Click the hammer icon on the toolbar (or go to Project > Build All). The IDE will now compile your code. Look at the "Console" window at the bottom. If everything is correct, you should see a message indicating a successful build with "0 errors, 0 warnings".

You have now successfully compiled your firmware! The IDE has created an .elf file in your project's Debug folder.


3. Flashing the Firmware to the Blue Pill

With the compiled firmware ready, the final step is to transfer it to the microcontroller's flash memory. This is done through the ST-Link's Serial Wire Debug (SWD) interface.

A key challenge with non-official "Blue Pill" boards and clone ST-Link debuggers is their sometimes-unreliable behavior with default IDE settings. The video you watched presents a professional-grade solution to this problem by using OpenOCD.

What is OpenOCD?
OpenOCD (Open On-Chip Debugger) is a powerful, open-source tool that acts as a bridge between your PC and the debugger (ST-Link). It is known for being more flexible and compatible with a wider range of hardware, including clones, than some proprietary tools.

Let's continue with the video to configure the IDE for flashing.

11. Install STM32 CubeIDE and LED blink program for Windows (OpenOCD included)

Now, let's watch the final and most important part of the same video. This section explains how to configure the IDE's 'Run' settings to use OpenOCD and flash the board.

Starting at 15:52, watch the firmware upload. Follow the steps carefully: Click the 'Run' button (the green play icon). In the 'Run Configurations' dialog, go to the 'Debugger' tab. Change the 'Debug probe' from 'ST-LINK (ST-LINK GDB server)' to 'ST-LINK (OpenOCD)'. Under 'Reset behavior', select 'Software system reset'. Click 'Apply', then 'OK'.

After you click 'OK', the IDE will use OpenOCD to connect to your ST-Link, transfer the compiled .elf file to the Blue Pill's flash memory, and start the program.

Verification:
Look at your Blue Pill board. The onboard green (or sometimes blue) LED connected to PC13 should now be blinking! Congratulations, you have successfully deployed your first bare-metal firmware.


4. Troubleshooting: When Things Don't Go as Planned

Working with clone hardware can sometimes be frustrating. If the flashing process fails with an error like "Could not verify ST device!" or "Failed to start GDB server," do not worry. This is a common experience, and solving it is part of becoming a competent engineer.

These errors are typical when using clone STM32 boards. They often relate to the debugger failing to connect or reset the chip properly.

Here is a very effective alternative method using a separate tool, STM32CubeProgrammer. This tool is solely dedicated to flashing and is often more robust for stubborn boards.

Getting Started with STM32 Blue Pill: Clock Setup & Code Upload with ST-Link Programmer | #stm32

If the IDE method failed, this video from Kitflix demonstrates a bulletproof workaround. It uses the standalone STM32CubeProgrammer tool and a physical trick to force the board into programming mode.

About 17 minutes into the video, watch the flashing process. The key steps are: Open STM32CubeProgrammer (you can install it from ST's website). Click 'Open file' and select the .elf file from your project's 'Debug' folder. The Trick: Press and HOLD the black RESET button on your Blue Pill board. While holding RESET, click the 'Connect' button in STM32CubeProgrammer. Once it says 'Data read successfully', release the RESET button. Click 'Download' to flash the firmware.

This "press-and-hold-reset" method works because it prevents the microcontroller from running any existing (and potentially problematic) code, allowing the debugger to establish a clean connection.

Test your understanding!

You've built your project, but you want to send the compiled firmware file to a colleague so they can flash it on their own board using STM32CubeProgrammer. Which file from your project's Debug folder would you send them?

Show answer

You would send them the .elf file (e.g., BareMetal_Blinky.elf). This file contains all the necessary machine code and is the standard format used by flashing and debugging tools. You could also convert it to a .hex or .bin file, but the .elf is the primary output.


Conclusion

You have successfully navigated a critical milestone in your embedded systems journey. You've taken your own C code, compiled it into a machine executable, and flashed it onto real hardware to produce a visible result.

Key Takeaways:

  • A toolchain (compiler, linker) turns human-readable C code into a machine-executable .elf file.
  • Compiling is done in STM32CubeIDE with the "Build" command (hammer icon).
  • Flashing is done with the "Run" command (play icon), which sends the code to the MCU via the ST-Link.
  • For clone hardware like the Blue Pill, configuring the debugger to use OpenOCD significantly improves reliability.
  • If the integrated IDE flashing fails, standalone tools like STM32CubeProgrammer combined with hardware tricks (like holding the reset button) provide a robust backup plan.

Preview of the Next Lesson:
Your LED is blinking, but what if it wasn't? How would you figure out what's wrong? The ST-Link is not just for flashing; it's a powerful debugger. In our next lesson, we will explore the final outcome of this module: Debug embedded code using breakpoints, register monitoring, and variable inspection. You will learn how to pause your code in real-time, inspect the state of registers and variables, and step through your program line-by-line, directly on the hardware.