Microcontrollers & architecture 3 min read

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.

Left: the Arm Cortex-M core has sixteen registers, R0 to R12 for general work plus SP, LR and PC with fixed jobs. Right: the GPIO output register sits at a memory address such as 0x4800_0014 on an STM32F0. Bit 5 is 1, so the LED on pin PA5 is on, while bit 0 is 0 and the LED on PA0 is off.
GPRs live inside the core; SFRs live in the peripherals.

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