How can two programs both use address 0x8000 without colliding? How can a program "see" more memory than the chip physically has? The answer to both is one of the most elegant ideas in computing: virtual memory, made real by the MMU. This is the hardware that turns a microcontroller into a computer that can run Linux.
Every address your program uses is a virtual address. It is not the real location in RAM. Between the CPU and memory sits the MMU (Memory Management Unit), which translates each virtual address into a physical address on the fly, for every single access.
That one layer of indirection buys an astonishing amount:
Translating every byte individually would be impossible, so memory is divided into fixed-size chunks called pages (commonly 4 KB). The MMU only needs to map page → page. The map itself is the page table, stored in memory: one entry per virtual page giving its physical frame plus permission bits.
A flat table for a 4 GB space would be huge, so ARM uses multi-level page tables (a tree). The CPU register TTBR (Translation Table Base Register) points to the current process's top-level table — switching it is how the OS switches address spaces on a context switch.
Walking a multi-level table means several memory reads per access — far too slow if done every time. So the MMU caches recent translations in the TLB (Translation Lookaside Buffer), a small, very fast lookup. Most accesses hit the TLB and translate in effectively one cycle; a miss triggers a page-table walk to fetch and cache the mapping.
The page table is the hotel's full guest register in the back office. The TLB is the receptionist's sticky notes for the guests who came by in the last minute. Most lookups are answered instantly from the notes; only an unfamiliar name needs a trip to the back office.
What if a virtual page isn't currently in RAM, or you touch one you're not allowed to? The MMU raises a page fault — an exception (Day 17) handled by the OS. The OS decides what to do:
This is how a system "runs more than its RAM": rarely used pages live on disk and are paged in on demand.
| MPU (Day 20) | MMU (today) | |
|---|---|---|
| Translation | none (physical only) | virtual → physical |
| Granularity | a few regions | fine-grained pages |
| Per-process space | no | yes |
| Typical core | Cortex-M / R | Cortex-A |
| Runs | bare-metal / RTOS | Linux, Android, rich OS |
The MPU only protects; the MMU translates and protects. That extra power is exactly what a general-purpose OS needs.
The MMU sits between CPU and RAM and translates every virtual address to a physical one using page tables, cached by the TLB for speed. This gives each process a private address space, lets the OS use disk as overflow via page faults, and is the dividing line between a microcontroller (MPU) and a full computer (MMU).
Hardware that translates virtual addresses to physical ones via page tables, giving each process a private address space.
A fast cache of recent virtual-to-physical translations; a miss triggers a page-table walk.
The MPU only protects fixed physical regions; the MMU also translates with fine-grained pages and per-process spaces.