Skip to content

RAM Loading for Development

Flash memory on ESP devices has a limited write endurance — typically 100,000 cycles. During active development, flashing dozens of times per day adds up. RAM loading bypasses flash entirely: you convert your ELF to a RAM binary, load it directly into the device’s SRAM, and it executes immediately. No flash wear, no erase cycles, faster iteration.

RAM loading is a good fit when:

  • You are iterating rapidly on application logic and want sub-second deploy cycles.
  • You want to preserve the existing flash contents (e.g., NVS data, calibration values).
  • You are testing on hardware that has already been through many flash cycles.

It is not a good fit when:

  • Your application depends on flash-resident features: NVS, SPIFFS, LittleFS, or OTA partitions.
  • Secure boot is enabled (RAM loading requires CONFIG_SECURE_BOOT=n).
  • Your binary is too large to fit in available SRAM.
  1. Build your project with ESP-IDF as usual. The build produces an ELF file (typically build/<project>.elf):

    Terminal window
    idf.py build
  2. Convert the ELF to a RAM binary using esp_elf_to_ram_binary:

    esp_elf_to_ram_binary({
    "elf_path": "build/my_project.elf",
    "chip": "esp32"
    })

    This produces a binary with RAM segments (IRAM/DRAM) placed first, suitable for direct loading. The output defaults to build/my_project-ram.bin.

  3. Load to the device with esp_load_ram:

    esp_load_ram({
    "binary_path": "build/my_project-ram.bin",
    "port": "/dev/ttyUSB0"
    })

    The binary transfers to RAM and begins executing immediately.

  4. Capture output with esp_serial_monitor:

    esp_serial_monitor({
    "port": "/dev/ttyUSB0",
    "baud_rate": 115200,
    "duration_seconds": 10,
    "reset_on_connect": false
    })

    Set reset_on_connect to false — resetting the device would stop the RAM-loaded code.

  5. Iterate: edit your source, rebuild, convert, load again. Steps 2-4 typically complete in a few seconds.

Your project must be configured to produce binaries compatible with RAM execution.

By default, esp_elf_to_ram_binary writes the output next to the ELF file with a -ram.bin suffix. To control the output location:

esp_elf_to_ram_binary({
"elf_path": "build/my_project.elf",
"output_path": "/tmp/test-ram.bin",
"chip": "auto"
})

Setting chip to "auto" lets esptool detect the target from the ELF metadata. Specify "esp32", "esp32s3", or "esp32c3" explicitly if auto-detection fails.

  • No flash-dependent features: NVS, SPIFFS, LittleFS, and OTA all read from flash. Code that calls these APIs will fail or return errors when running from RAM.
  • No persistence: the loaded code runs until the device is reset. A hardware reset or power cycle returns the device to whatever firmware is in flash (or the ROM bootloader if flash is blank).
  • SRAM size limits: ESP32 has roughly 520KB of SRAM. Large applications or those with heavy static allocations may not fit. The esp_elf_to_ram_binary tool reports the output file size — compare this against your chip’s available RAM.
  • Cannot stop remotely: once loaded, execution continues until a physical reset. There is no software-only stop mechanism through mcesptool.