Before diving into specifics, it helps to understand the two fundamental memory architectures.
Von Neumann architecture uses a single address space for both program code and data. Reading an instruction and reading a variable share the same bus. Most general-purpose computers use this model.
Harvard architecture uses separate buses and address spaces for program memory and data memory. Code and data cannot be mixed without explicit hardware support. AVR microcontrollers are strict Harvard machines. The ESP32 is a modified Harvard architecture — it has separate instruction and data caches, but the underlying SPI Flash is accessible as both code and data through different mechanisms.
This distinction has a direct practical consequence: on AVR, a constant string in your sketch lives in Flash by default only if you place it there explicitly. Otherwise the compiler copies it into SRAM at startup.
A typical ATmega328P (Arduino Uno) has three distinct memory regions:
PROGMEMLPM) to readHigh address ┌─────────────┐
│ Stack │ grows downward
│ ↓ │
│ (free RAM) │
│ ↑ │
│ Heap │ grows upward (malloc/new)
│─────────────│
│ BSS │ zero-initialized globals
│─────────────│
│ Data │ initialized globals/statics
Low address └─────────────┘
EEPROM.h library| Board | Flash | SRAM | EEPROM |
|---|---|---|---|
| Uno (ATmega328P) | 32 KB | 2 KB | 1 KB |
| Nano (ATmega328P) | 32 KB | 2 KB | 1 KB |
| Mega (ATmega2560) | 256 KB | 8 KB | 4 KB |
| Leonardo (ATmega32U4) | 32 KB | 2.5 KB | 1 KB |
The ESP32 has a richer memory landscape. The internal memory is split into several named regions, each with different properties.
The ESP32 has approximately 520 KB of internal SRAM divided into three banks:
SRAM0 (192 KB) — IRAM
IRAM_ATTRSRAM1 (128 KB) — DRAM/IRAM shared
SRAM2 (200 KB) — DRAM
In practice, after the system libraries (WiFi stack, BT stack, FreeRTOS), you typically have 200–300 KB of heap available.
RTC_DATA_ATTR// Variable that survives deep sleep
RTC_DATA_ATTR int bootCount = 0;
Some ESP32 modules (e.g., ESP32-WROVER) include 4 or 8 MB of external PSRAM (pseudo-static RAM) connected via SPI. It is slower than internal SRAM (higher latency, lower bandwidth) but dramatically increases available heap for large buffers, image processing, or web serving.
Enable in Arduino-ESP32: Board settings → PSRAM → Enabled.
External Flash chip connected via SPI (or QSPI). Contains:
Flash is not directly addressable as RAM. Code is fetched through a cache (MMU), and data must be explicitly read via APIs.
| Region | Size | Volatile | CPU Access | Use |
|---|---|---|---|---|
| IRAM | ~192 KB | Yes | Fast | ISR, WiFi stack, time-critical code |
| DRAM | ~160 KB | Yes | Fast | Heap, globals, stack |
| RTC Fast | 8 KB | No (deep sleep) | Fast | Persistent variables |
| RTC Slow | 8 KB | No (deep sleep) | Slow | ULP programs |
| PSRAM | 4–8 MB | Yes | Medium | Large buffers |
| SPI Flash | 4–16 MB | No | Via cache/API | Firmware, filesystem |
extern int __heap_start, *__brkval;
int freeRam() {
int v;
return (int)&v - (__brkval == 0
? (int)&__heap_start
: (int)__brkval);
}
void printMemInfo() {
Serial.printf("Free heap: %u bytes\n", ESP.getFreeHeap());
Serial.printf("Min free heap: %u bytes\n", ESP.getMinFreeHeap());
Serial.printf("Free PSRAM: %u bytes\n", ESP.getFreePsram());
}
| Previous: Introduction | Next: RAM Management | Home |