Bare-Metal Programming: AVR vs ARM/STM32
Embedded → Bare-Metal / Register-Level Programming
"Bare-metal" is a technique, not a chip
Bare-metal programming means writing directly to a chip's memory-mapped registers instead of calling a vendor HAL function like HAL_GPIO_Init() or digitalWrite()— the same idea on every chip. What changes is which registers exist, what they're called, and where they live — every manufacturer defines its own map. The video below walks through the idea on AVR (Arduino Uno/ATTiny85), while every other lesson in this section uses ARM Cortex-M / STM32 — same concept, different register names.
The same idea, two vendors' names for it
| Step | AVR (ATmega328P) | ARM/STM32 (F4-series) |
|---|---|---|
| Set pin direction | DDRB |= (1 << PB5); | GPIOA_MODER |= (0x1u << (5*2)); |
| Read pin direction back | DDRB & (1 << PB5) | GPIOA_MODER & (0x3u << (5*2)) |
| Drive pin high | PORTB |= (1 << PB5); | GPIOA_ODR |= (1u << 5); |
| Drive pin low | PORTB &= ~(1 << PB5); | GPIOA_ODR &= ~(1u << 5); |
| Read pin level | PINB & (1 << PB5) | GPIOA_IDR & (1u << 5) |
MODERuses two bits per pin (it also encodes alternate-function and analog modes — AVR pins can't do that without a separate peripheral). That two-bit-vs-one-bit difference is exactly the kind of detail you only notice by comparing two real register maps side by side, not from a single chip's documentation alone.Why this works · explanation & key points
Both families reduce "configure a pin as output, then drive it high" to the same two steps — set a direction bit, then set a data bit — they just use different register names and bit layouts to do it:
Try it — flip between the two register maps
// ATmega328P — set PB5 (Arduino Uno's built-in LED) as output, then high DDRB |= (1 << PB5); // 1 bit per pin: 1 = output PORTB |= (1 << PB5); // 1 bit per pin: 1 = high
Why this works · explanation & key points
Same operation — set PB5/PA5 as output, drive it high — written for each chip family:
What comes next in this section
Every remaining lesson in Bare-Metal / Register-Level Programming— linker scripts, the startup file, the vector table, ISR handlers, the clock tree, and writing a real peripheral driver from a reference manual — uses ARM Cortex-M / STM32 register names and addresses, matching the rest of this track's board and worked examples.
Completion saves automatically after you read through to the end.
Next lesson →