Embedded & Bare-Metal

bare-metal programming

/ bair-MET-ul /

Picture a tiny chip in a thermostat, a toothbrush, or a washing machine. There is no Windows, no Linux, no desktop, no files, no terminal — when the power comes on, YOUR code is the very first and only thing running, and it speaks directly to the hardware. Bare-metal programming means writing software that runs on a processor with NO operating system underneath it. Your program owns the whole machine.

Concretely, in a hosted environment (a PC running Linux) the operating system gives you a process with a virtual address space, a heap from malloc(), a console through printf(), and it loads and starts your program for you. On bare metal you have none of that for free. You write the startup code that runs before main(), you decide where in memory each thing lives via a linker script, you talk to a light or a sensor by writing specific numbers to specific hardware addresses (memory-mapped registers), and if you want printf() to send characters somewhere you must wire it up yourself. The C standard calls this a freestanding implementation: only a small part of the standard library is guaranteed (things like <stddef.h> and <stdint.h>), not the hosted parts like <stdio.h> that assume an OS.

It matters because most computers in the world are NOT laptops — they are billions of small microcontrollers in cars, medical devices, and appliances, and many run bare metal for cost, size, power, or timing reasons. The honest caveat: bare metal does not mean 'simple'. You give up the conveniences and the safety nets an OS provides (memory protection, scheduling, drivers), so a single wrong address or a missed hardware quirk can hang the whole device with no error message at all. Bare metal trades convenience for total, direct control.

// A whole bare-metal program: blink an LED, forever. volatile uint32_t *GPIO_OUT = (uint32_t *)0x40020014; int main(void) { for (;;) { *GPIO_OUT ^= (1u << 5); // toggle pin 5 for (volatile int i = 0; i < 100000; i++) { } // crude delay } }

No OS, no printf, no return: main never ends. The LED address is a fixed hardware location, and the loop just runs forever.

On bare metal main() typically never returns — there is nothing to return TO. Returning from main on a microcontroller usually falls into an infinite loop or a fault, so embedded main() is almost always for(;;) or while(1).

Also called
no-OS programmingfreestanding programming無作業系統程式設計裸機開發