Skip to content

LED: see the machine clearly, take the macros apart, climb to the types ​

Blinking an LED is the hello world of the microcontroller world, but this stop is in no hurry to blink. The first piece looks at the Cortex-M3 inside the BluePill from the inside out: how the two manuals split their jobs now that ARM sells blueprints but fabricates no chips, the core's whole estate of a handful of registers plus a three-stage pipeline, and the 4GB address map the architecture has fixed in stone — then the Renode routing logs bring the gavel down on "the CPU offers the outside world nothing but reads and writes". The suspense of a full-firmware instruction census is planted in that piece too, to be cashed in by disassembly in the second — every claim carries a manual citation, and every key step actually runs and reproduces.

With the machine in plain sight, we light the lamp from scratch and answer a more fundamental question: when we type GPIOC->CRH = x, what essentially happens? The answer: a single write to a fixed memory address, which the bus routes to a bank of switching circuits in the peripheral. That one sentence is the foundation of all embedded peripheral programming, and the second piece takes it apart and grinds it fine, with a stretch of modern C++ pseudocode as the cross-check.

With the foundation laid, we do it by that essence: RCC's clock gating answers "is this peripheral powered on", the four bits per pin in CRL/CRH answer "which gear is this piece of circuit twisted to", and ODR and BSRR answer "how do we flip a pin over" — we touch every one of those registers by hand with Renode and GDB, including one genuine crash: the configuration written into the wrong half of a register, and the LED dies on you out of spite. Then a hardware interlude makes the circuit inside a pin clear: push-pull, open-drain, Schmitt triggers, pull-up and pull-down — look back at those configuration bits and they are all knobs for choosing gears on real transistors. Finally, the staircase: what hidden wounds the C-macro-era wrappers left behind, what is rolled up inside the HAL's wrapping paper, all the way up to the Gpio template in estdx — port, pin, direction, and polarity all written into types, so misconfigured code is pinned down by the compiler the very second you hit Enter. Every layer's bill is settled on the spot with size and disassembly: zero overhead is not a slogan, it is an instruction count.

Chapter Navigation ​

pdf-latest-4-g85128cc · 85128cc · 2026-10-05