In short: RAM holds your running variables and is volatile and infinitely rewritable; Flash stores your program and constants with huge capacity but coarse block erases and ~10k–100k write cycles; EEPROM is the small, byte-addressable store for settings that must survive power loss with the highest endurance of the three.
Every microcontroller (MCU) ships with three memory technologies working together, and confusing them is one of the fastest ways to corrupt data, brick a bootloader, or watch a variable mysteriously reset. If you have ever asked "why does my calibration value vanish on reboot?" or "why can't I just write one byte to Flash like I do to RAM?", the answer lives in the physics and architecture of these three stores. Let us walk through endurance, access granularity, wear leveling, and the single most practical question for a firmware engineer: where do my variables actually live?
The three memories at a glance
On a typical Arm Cortex-M part such as an STM32F4 or an NXP Kinetis device, the address map carves out distinct regions. Flash is mapped at 0x08000000, SRAM at 0x20000000, and emulated or dedicated EEPROM sits in its own window. They differ not just in size but in how you are physically allowed to touch them.
| Property | RAM (SRAM) | Flash (NOR) | EEPROM |
|---|---|---|---|
| Volatility | Volatile (lost on power-off) | Non-volatile | Non-volatile |
| Typical size | 4 KB – 512 KB | 32 KB – 2 MB | 128 B – 16 KB |
| Write granularity | Byte / word | Word to program, block/page to erase | Byte |
| Endurance (write cycles) | Effectively unlimited | ~10,000 – 100,000 per page | ~100,000 – 1,000,000 per byte |
| Access speed | Fastest (single cycle) | Fast read, slow erase (ms) | Slow write (ms) |
| Holds | Stack, heap, globals, buffers | Code, const tables, firmware | Settings, counters, calibration |
The defining asymmetry of Flash: you can program individual words (flip 1→0), but you can only erase in large pages (flip 0→1), often 2 KB, 4 KB, or 128 KB at a time. That one rule drives nearly every design decision around non-volatile storage.
Why Flash cannot behave like RAM
A NOR Flash cell stores charge on a floating gate. Programming injects electrons to represent a 0; erasing tunnels them off to restore a 1. Because erase is a high-voltage, whole-block operation, you cannot change a single byte from 0x3F to 0x40 in place. To "update" one byte you must erase the entire surrounding page and rewrite it. This is why embedded logging, firmware updates, and settings storage all revolve around page management rather than simple pointer writes.
Where do my variables live?
This is the question every embedded C newcomer gets wrong once. The linker, not you, decides placement based on how a symbol is declared:
- Local variables (
int x;inside a function) live on the stack in RAM. They vanish when the function returns. - Initialized globals (
int gCount = 5;) live in.data: the initial value is stored in Flash and copied to RAM by the startup code beforemain(). - Zero-initialized globals (
static int buf[256];) go to.bssin RAM and are cleared at boot. - Constants (
const uint8_t lut[] = {...};) stay in.rodatain Flash and are read in place, never copied. - Dynamic allocations (
malloc) come from the heap in RAM.
A 10 KB const lookup table costs you 10 KB of Flash and zero RAM. The same table without const is copied into RAM at startup, costing you 10 KB of both. On a 32 KB-RAM part, that single keyword is the difference between fitting and overflowing.
Endurance and wear leveling
Because Flash and EEPROM cells degrade with every erase/program cycle, a naive design that rewrites the same page on every update will wear it out. At 10,000 cycles, a datalogger writing once per second kills a page in under three hours. Wear leveling spreads writes across many physical locations so no single cell is hammered.
The classic MCU technique is EEPROM emulation: dedicate two Flash pages and, instead of overwriting a value, append a new (virtual-address, value) record to the active page. When the page fills, valid records are migrated to the second page and the first is erased. ST's X-CUBE EEPROM library and NXP's FTFx drivers both implement exactly this. The effective endurance multiplies by the number of records a page can hold.
Access speed and the execution picture
RAM reads and writes complete in a single clock cycle; that is why the CPU executes from it fastest and why time-critical routines are sometimes copied into RAM (__attribute__((section(".ramfunc")))). Flash reads are nearly as fast at low clock speeds but need wait states above ~30 MHz, which is why vendors add prefetch buffers and caches (ST's ART Accelerator, for example). Flash and EEPROM writes, however, take milliseconds and typically stall the Flash interface — on many parts you cannot fetch code from Flash while erasing it, so the write routine itself must run from RAM. EEPROM hides this behind its controller but is still orders of magnitude slower than RAM.
Practical rules for firmware engineers
- Never store a frequently-changing counter directly in a fixed Flash location without wear leveling.
- Mark large constant tables
constso they stay in Flash and spare your RAM. - Validate persisted data with a CRC; a power loss mid-write leaves EEPROM/Flash in an indeterminate state.
- Prefer true EEPROM (or FRAM) for data updated thousands of times a day; its endurance dwarfs Flash.
- Remember that understanding the address map is the foundation for memory-mapped I/O and peripheral programming.
Teams doing serious embedded and silicon work verify these behaviors in simulation and on-target; for RTL and verification training that complements firmware skills, our sister brand ChipXpert VLSI training covers the hardware side in depth. If you are building the design itself, interrupt latency fundamentals is a natural next read.
Want to master memory architecture, bare-metal C, and the Cortex-M toolchain hands-on? Explore our Embedded Systems track on CourseTron Courses and build real firmware from the first lesson.
Frequently Asked Questions
Can I use Flash as extra RAM?
Not for read/write data. Flash is read-in-place for code and constants, but it cannot be written byte-by-byte or erased quickly. Use it only for values that change rarely. For scratch data you always need genuine RAM.
Why does my global variable keep its value but a local one does not?
Globals live in .data or .bss in RAM for the whole program lifetime, so they persist across function calls (but still reset on power-off). Locals live on the stack and are reclaimed the moment the function returns.
Is EEPROM always a separate chip?
No. Some MCUs have dedicated on-die EEPROM; many modern parts have none and instead emulate EEPROM inside Flash using wear-leveling libraries. External I2C/SPI EEPROMs and FRAM are also common when you need high endurance.
What happens if power is lost during a Flash write?
The cell can be left half-programmed, so the stored value is unreliable. Robust designs use a two-copy scheme with a CRC or a valid-flag written last, so the firmware can detect and discard a torn write on the next boot.