Skip to content

Flash Operations

The Flash Manager component provides 7 tools for reading, writing, erasing, and verifying ESP device flash memory. All operations shell out to esptool as async subprocesses and support both physical serial ports and QEMU socket:// URIs.


Write a single firmware binary to flash at a specified address using esptool write-flash.

NameTypeDefaultDescription
firmware_pathstr(required)Path to the firmware binary (.bin) file.
portstr | NoneNoneSerial port or socket:// URI. Required — returns error if omitted.
addressstr"0x0"Flash address to write to (hex string). Use partition offsets for non-firmware images.
verifyboolTrueVerify flash contents after writing.
# Flash application firmware at the standard app offset
result = await client.call_tool("esp_flash_firmware", {
"firmware_path": "/build/app.bin",
"port": "/dev/ttyUSB0",
"address": "0x10000",
"verify": True
})
# Flash a filesystem image at a custom offset
result = await client.call_tool("esp_flash_firmware", {
"firmware_path": "/build/littlefs.bin",
"port": "socket://localhost:5555",
"address": "0x290000"
})
{
"success": true,
"port": "/dev/ttyUSB0",
"firmware_path": "/build/app.bin",
"address": "0x10000",
"firmware_size": 524288,
"bytes_written": 524288,
"verified": true,
"elapsed_seconds": 12.3
}

Flash multiple binary files at different addresses in a single esptool write-flash invocation. Faster than separate flash operations because it connects to the device only once.

NameTypeDefaultDescription
fileslist[dict](required)List of objects with address (hex string) and path (file path).
portstr | NoneNoneSerial port or socket:// URI. Required.
verifyboolTrueVerify flash contents after writing.
compressboolTrueUse compression for faster transfer.

Each entry in files must have exactly two keys:

KeyTypeDescription
addressstrHex flash offset (e.g., "0x0", "0x8000", "0x10000").
pathstrAbsolute path to the binary file.
result = await client.call_tool("esp_flash_multi", {
"files": [
{"address": "0x0", "path": "/build/bootloader.bin"},
{"address": "0x8000", "path": "/build/partitions.bin"},
{"address": "0x10000", "path": "/build/app.bin"}
],
"port": "/dev/ttyUSB0",
"verify": True,
"compress": True
})
{
"success": true,
"port": "/dev/ttyUSB0",
"files": [
{"address": "0x0", "path": "/build/bootloader.bin", "size": 26384},
{"address": "0x8000", "path": "/build/partitions.bin", "size": 3072},
{"address": "0x10000", "path": "/build/app.bin", "size": 524288}
],
"file_count": 3,
"total_size": 553744,
"bytes_written": 553744,
"compressed": true,
"verified": true,
"elapsed_seconds": 15.7
}

Read raw bytes from flash memory and save them to a file. If size is not specified, the tool auto-detects the flash size and reads the entire contents.

NameTypeDefaultDescription
output_pathstr(required)File path to save the flash contents. Parent directories are created automatically.
portstr | NoneNoneSerial port or socket:// URI. Required.
start_addressstr"0x0"Flash offset to start reading from (hex string).
sizestr | NoneNoneNumber of bytes to read (hex or decimal string). Reads entire flash if omitted.
# Read entire flash
result = await client.call_tool("esp_flash_read", {
"output_path": "/backups/device_flash.bin",
"port": "/dev/ttyUSB0"
})
# Read just the partition table region
result = await client.call_tool("esp_flash_read", {
"output_path": "/backups/partitions.bin",
"port": "/dev/ttyUSB0",
"start_address": "0x8000",
"size": "0xC00"
})
{
"success": true,
"port": "/dev/ttyUSB0",
"output_path": "/backups/device_flash.bin",
"start_address": "0x0",
"bytes_read": 4194304,
"elapsed_seconds": 45.2
}

Erase flash memory. Without a size parameter, the entire flash is erased. With size, only the specified region is erased. Erased bytes become 0xFF.

NameTypeDefaultDescription
portstr | NoneNoneSerial port or socket:// URI. Required.
start_addressstr"0x0"Flash offset to start erasing (hex string).
sizestr | NoneNoneNumber of bytes to erase (hex or decimal string). Erases entire flash if omitted.
result = await client.call_tool("esp_flash_erase", {
"port": "/dev/ttyUSB0"
})
{
"success": true,
"port": "/dev/ttyUSB0",
"erase_type": "full",
"start_address": "0x0",
"size": null,
"elapsed_seconds": 8.5
}

For region erases, erase_type is "region" and size contains the requested byte count.


Create a complete flash backup by reading the entire flash to a file. This is a convenience wrapper around esp_flash_read that handles address and size selection.

The resulting file can be restored with esp_flash_firmware.

NameTypeDefaultDescription
backup_pathstr(required)File path to save the backup.
portstr | NoneNoneSerial port or socket:// URI. Required.
include_bootloaderboolTrueStart from address 0x0 to include the bootloader. When False, starts at 0x1000.
result = await client.call_tool("esp_flash_backup", {
"backup_path": "/backups/full_device_20260223.bin",
"port": "/dev/ttyUSB0",
"include_bootloader": True
})

The return value matches esp_flash_read. The start_address will be "0x0" or "0x1000" depending on include_bootloader.

{
"success": true,
"port": "/dev/ttyUSB0",
"output_path": "/backups/full_device_20260223.bin",
"start_address": "0x0",
"bytes_read": 4194304,
"elapsed_seconds": 45.2
}

Verify that flash contents at a given address match a local binary file, without re-flashing. Uses esptool verify-flash internally.

Useful for confirming a successful flash operation or checking whether an update is needed.

NameTypeDefaultDescription
firmware_pathstr(required)Path to the binary file to compare against.
portstr | NoneNoneSerial port or socket:// URI. Required.
addressstr"0x0"Flash address to verify from (hex string).
result = await client.call_tool("esp_verify_flash", {
"firmware_path": "/build/app.bin",
"port": "/dev/ttyUSB0",
"address": "0x10000"
})

On match:

{
"success": true,
"verified": true,
"port": "/dev/ttyUSB0",
"firmware_path": "/build/app.bin",
"address": "0x10000",
"file_size": 524288,
"elapsed_seconds": 8.1
}

On mismatch:

{
"success": true,
"verified": false,
"mismatch": true,
"port": "/dev/ttyUSB0",
"firmware_path": "/build/app.bin",
"address": "0x10000",
"file_size": 524288,
"elapsed_seconds": 8.3,
"details": "Verify failed at offset 0x00001000..."
}

Note that a mismatch still returns "success": true because the verification operation itself completed without error. Check the verified field to determine the outcome.