ARM Architecture

ARM processors power almost every phone and most microcontrollers. Learn the ARM RISC philosophy, profiles (Cortex-A, R, M), register file (R0–R15, CPSR/xPSR), load/store architecture, Thumb-2 instructions, condition codes, the AAPCS calling convention, pipelines, and ARM assembly examples.

ARM licenses its processor designs to chip makers, so billions of cores ship each year — from tiny Cortex-M0 sensors to Apple and Qualcomm application processors. Its energy efficiency comes from a clean RISC design.

An analogy

ARM is like a well-organised workshop where every tool must be brought to the bench (registers) before use — no working directly in the storeroom (memory). That rule keeps work fast and predictable.

Profiles

Cortex-A (application: Linux/Android, MMU, high performance), Cortex-R (real-time: automotive, storage controllers, lockstep safety), Cortex-M (microcontrollers: low power, deterministic interrupts).

Instruction set

32-bit ARM (A32), compact Thumb/Thumb-2 (T32, mixed 16/32-bit) used by Cortex-M, and 64-bit A64 in ARMv8-A. Many instructions can set flags (S suffix) and execute conditionally (IT blocks in Thumb).

Modes and exceptions

Cortex-M has Thread and Handler modes, MSP/PSP stacks, and the NVIC with automatic register stacking on interrupt entry. Cortex-A has exception levels EL0–EL3 for user, OS, hypervisor and secure monitor.

Microarchitecture

Pipelines from 2–3 stages (M0) to deep out-of-order (A7x/X). big.LITTLE mixes efficient and fast cores. Extensions: DSP and FPU (M4/M7), Helium/M-Profile Vector (M55), NEON/SVE (A-class), TrustZone security.

Formulas

Worked example: Performance estimate

Given: Cortex-M4 ≈ 1.25 DMIPS/MHz at 168 MHz

Find: DMIPS.

Answer: ≈ 210 DMIPS

Worked example: Load/store

Given: Increment a variable in memory at address in R0

Find: Instructions.

Answer: 3 instructions (no memory-to-memory ALU ops)

Sum an array in ARM Thumb-2 assembly

    .syntax unified
    .thumb
    .global sum_array
@ uint32_t sum_array(const uint32_t *p, uint32_t n);
@ R0 = p, R1 = n, result in R0
sum_array:
    movs    r2, #0          @ sum = 0
    cbz     r1, done        @ if n == 0 return 0
loop:
    ldr     r3, [r0], #4    @ r3 = *p; p += 4 (post-index)
    adds    r2, r2, r3      @ sum += r3
    subs    r1, r1, #1      @ n--
    bne     loop            @ repeat while n != 0
done:
    mov     r0, r2          @ return sum
    bx      lr

Arguments arrive in R0/R1 per AAPCS; post-indexed LDR loads and advances the pointer in one instruction; BX LR returns. A C compiler generates almost the same code.

Common mistakes

Applications

Key takeaways

Going further