Registers: GPRs vs SFRs
General-purpose registers (GPRs) are the CPU's own tiny, fast scratchpad for calculations. Special-function registers (SFRs) sit at memory addresses and control the hardware: writing one bit can light an LED, start a timer or send a byte.
General-purpose registers
A Cortex-M core has sixteen 32-bit registers. R0 to R12 are free for general work, while R13 is the stack pointer (SP), R14 the link register (LR) holding the return address, and R15 the program counter (PC). Arm is a load/store design: arithmetic only works on registers, so values are loaded from memory, processed, and stored back.
You rarely name them in C, because the compiler juggles them for you. The calling convention passes the first four arguments in R0 to R3 and returns the result in R0, so this function compiles to just two instructions:
int add(int a, int b) { return a + b; }
add: adds r0, r0, r1 @ a + b, result in r0
bx lr @ return to the caller
Special-function registers
SFRs belong to peripherals and live in the memory map. Each bit or group of bits has a meaning documented in the reference manual. Some configure (enable, mode), some report status (flags such as "transmit buffer empty") and some carry data (the byte to send or just received). Turning on an LED on an STM32F0 takes three of them:
RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // 1. clock the GPIOA peripheral
GPIOA->MODER |= (1u << (5 * 2)); // 2. make PA5 an output
GPIOA->ODR |= (1u << 5); // 3. drive PA5 high
Two traps to know
volatile: SFRs can change on their own, so every access must really happen. Vendor headers declare themvolatilefor you.- Read-modify-write:
|=reads, changes, then writes. An interrupt in between can lose an update. Many STM32 GPIOs offer a set/reset register for atomic writes:GPIOA->BSRR = (1u << 5);