Skip to content
Tech News
← Back to articles

Bare-metal STM32: vector table, linker script, and startup code from scratch

read original get STM32 Development Kit → more articles
Why This Matters

This article highlights the importance of understanding low-level embedded development by building a bare-metal STM32 project from scratch. It emphasizes how gaining direct control over hardware fosters deeper learning and flexibility, which is crucial for advanced embedded applications and innovation in the tech industry. For consumers, this approach can lead to more optimized and reliable devices tailored to specific needs.

Key Takeaways

I recently bought myself an STM32 Nucleo microcontroller board to play around with. What fascinated me was how much more flexible things are at this level, how much more you can do yourself. With an ESP32 that’s not really the case, you’re always tied to ESP-IDF or some other framework.

I started with a first simple example, the kind everyone knows and has done before: the famous Hello World. It’s simple, and that’s exactly why it’s useful. You don’t learn a language’s syntax with it, it’s too small for that. You learn how to actually use the language. What file format, how to compile, how to link, how to run the result.

That’s why I always reach for Hello World first whenever I pick up a new language or a new environment. It forces me to run the whole build system once before I do anything else. Two things I learned this way that weren’t obvious to me at the start. First: you can learn a surprising amount from a simple example if you take it seriously. Second: simple is almost never really simple. Most things that look easy are easy because someone else hid the complexity for you.

The embedded world has a Hello World too: the blinking LED. Most microcontroller boards have an onboard LED that you turn on and off at some frequency. Sounds trivial. And it is, if you use a Hardware Abstraction Layer (HAL) and some ready-made project template.

I’ve been working in automotive software for years, and before that on physics simulations at university. In my head I’d always been “close to the hardware”, I write embedded software after all, not frontend. A while back I wrote about the roles of C, C++, and Rust in automotive and quietly took for granted that “embedded equals close to the hardware”. At some point it hit me that this was a delusion. MCAL, AUTOSAR OS, RTE: there are more layers between me and the silicon than between a web app and the kernel. I wanted to actually get down to the bottom for once. No HAL, no framework, no vendor black box. Just the reference manual and the compiler.

A Blinky in Rust

In the Rust ecosystem the example quickly ends up looking like this:

#![no_std] #![no_main] use cortex_m_rt :: entry ; use panic_halt as _ ; use stm32f4xx_hal ::{ pac , prelude :: * }; #[entry] fn main () -> ! { let dp = pac :: Peripherals :: take () .unwrap (); let rcc = dp .RCC .constrain (); let clocks = rcc .cfgr .sysclk ( 48 .MHz ()) .freeze (); let gpiob = dp .GPIOB .split (); let mut led1 = gpiob .pb0 .into_push_pull_output (); let mut led2 = gpiob .pb7 .into_push_pull_output (); let mut delay = dp .TIM1 .delay_ms ( & clocks ); loop { led1 .toggle (); delay .delay_ms ( 400u32 ); led2 .toggle (); delay .delay_ms ( 100u32 ); } }

It’s short, type-safe, and it works. The compiler keeps me from toggling an input pin. The clock config goes through a builder pattern. Pin types carry their configuration in the type system, so toggle() on an input pin is a compile error. The delay is timed off SYSCLK. And everything you don’t see, the vector table, the reset handler, the copy loop for .data , the zeroing of .bss , all of that comes from the cortex-m-rt crate. The linker just gets a small memory.x that tells it where flash and RAM are.

That’s exactly the problem I wanted to dig into. Not in the “the HAL is bad” sense (I actually came away appreciating it more), but: I wanted to see what the HAL does for me. So the same thing again, but in C, no HAL, no CMSIS, just register addresses straight out of the reference manual.

... continue reading