# configure_write_flash_args in esp_flasher: How It Prepares ESP Flashing Parameters

> Learn how configure_write_flash_args prepares ESP flashing parameters by mapping firmware binaries and settings to flash offsets for ESP32 and ESP8266 devices.

- Repository: [Jason2866/esp_flasher](https://github.com/jason2866/esp_flasher)
- Tags: internals
- Published: 2026-03-04

---

**The `configure_write_flash_args` function translates raw firmware binaries and user settings into a structured `MockEsptoolArgs` object that maps each component to its correct flash memory offset for ESP32 and ESP8266 devices.**

The `configure_write_flash_args` function serves as the central preprocessing hub in the `jason2866/esp_flasher` repository. Located in [`esp_flasher/common.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/common.py), this helper bridges the gap between user-provided firmware files and the low-level flashing operations required by different ESP chip families.

## What Is configure_write_flash_args?

Located at lines 54-86 in [`esp_flasher/common.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/common.py), `configure_write_flash_args` is a factory function that prepares all necessary arguments for the ESP flashing process. It accepts chip detection information, firmware paths, and configuration flags, then returns a fully populated `MockEsptoolArgs` instance.

The function acts as a translation layer between the graphical user interface (defined in [`esp_flasher/gui.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/gui.py)) and the underlying `esptool` wrapper (implemented in [`esp_flasher/own_esptool.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/own_esptool.py)).

## How configure_write_flash_args Prepares Flashing Parameters

The function executes a multi-step pipeline to ensure the ESP chip receives correctly formatted data at the proper memory addresses.

### Step 1: Read Firmware Metadata

The function first calls `read_firmware_info` to analyze the input binary. This detection identifies the **flash mode**, **flash frequency**, and whether the binary is a pre-built *factory* image. According to the source code, this determination controls whether additional supporting files (bootloader, partition table, OTA data) must be appended.

### Step 2: Identify ESP32 Family and Model

Using the `info.model` field (e.g., *ESP32-C2*, *ESP32-S3*, *ESP32-P4*), the function sets three critical variables:
- `model`: The normalized chip identifier
- `safeboot`: The appropriate safe-boot binary name
- Bootloader offset address

Different ESP32 families require distinct bootloader binaries and memory layouts, making this chip-specific routing essential.

### Step 3: Validate Flash Frequency

The function enforces hardware compatibility by rejecting unsupported flash frequencies. Specifically, it throws an error for frequencies of **15 MHz, 20 MHz, 26 MHz, or 30 MHz**, as these lack corresponding bootloader support in the repository.

### Step 4: Resolve File Locations

`configure_write_flash_args` builds absolute paths for all required binaries:
- Bootloader ELF (downloaded via `format_bootloader_path` if not local)
- Partitions CSV (formatted via `format_partitions_path`)
- OTA data binary
- Safe-boot binary

The helper function `open_downloadable_binary` (from [`esp_flasher/helpers.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/helpers.py)) handles HTTP downloads when local files are missing.

### Step 5: Convert ELF to Binary

If the bootloader is provided as an ELF file, the function reads it into a `BytesIO` object and converts it to a raw `.bin` format. The ESP flashing routines require binary files, not ELF objects, so this conversion is mandatory.

### Step 6: Populate Address-File Mappings

The function constructs the `addr_filename` list, which maps memory offsets to binary streams:
- **Non-factory images**: Adds entries for bootloader, partitions, OTA data, safe-boot, and user firmware at their respective offsets (e.g., `0x1000`, `0x8000`, `0xe000`, `0x3f0000`).
- **Factory images**: Adds only the single firmware binary at address `0x0`.

This mapping ensures each component is written to the correct location in the ESP's flash memory.

### Step 7: Create MockEsptoolArgs Wrapper

Finally, the function instantiates and returns a `MockEsptoolArgs` object containing:
- Chip type (`chip`)
- Flash size (`flash_size`)
- Address-file list (`addr_filename`)
- Flash mode and frequency
- Input bootloader path
- Security flags (`secure_pad`, `secure_pad_v2`)
- Revision limits (`min_rev`, `min_rev_full`, `max_rev_full`)

This wrapper mimics the command-line interface of `esptool`, allowing [`esp_flasher/own_esptool.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/own_esptool.py) to execute the flash operation using a consistent API.

## Code Example: Using configure_write_flash_args

Below is a practical example demonstrating how the GUI layer calls this function after detecting the connected chip:

```python
from esp_flasher.common import configure_write_flash_args
from esp_flasher.own_esptool import flash_firmware

# Assume info is an ESPChipInfo object from detect_chip()

info = detect_chip(serial_port)

# Prepare arguments for a standard ESP32-S3 firmware flash

args = configure_write_flash_args(
    info=info,
    chip=None,
    flag_factory=False,
    factory_firm_path=None,
    firmware_path="firmware.bin",
    flash_size="8MB",
    bootloader_path="https://example.com/bootloader.elf",
    partitions_path="partitions.csv",
    otadata_path="ota_data_initial.bin",
    input=None,
    secure_pad="False",
    secure_pad_v2="False",
    min_rev=0,
    min_rev_full=0,
    max_rev_full=65535,
    elf_sha256_offset="",
    use_segments="False",
    flash_mmu_page_size="",
    pad_to_size="",
    spi_connection="",
    output=None,
)

# Execute the flash operation

flash_firmware(args)

```

To inspect the generated parameters before flashing:

```python
print(f"Target chip: {args.chip}")
print(f"Flash size: {args.flash_size}")
print(f"Flash mode: {args.flash_mode}")

for offset, stream in args.addr_filename:
    print(f"Write 0x{offset:05x}: {stream.name if hasattr(stream, 'name') else 'binary stream'}")

```

## Key Files in the Flashing Pipeline

The `configure_write_flash_args` function sits at the center of a coordinated file structure:

| File | Purpose | Key Interaction |
|------|---------|-----------------|
| [`esp_flasher/common.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/common.py) | Contains `configure_write_flash_args`, `MockEsptoolArgs`, and path formatting helpers. | Central factory for flash arguments. |
| [`esp_flasher/own_esptool.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/own_esptool.py) | Wraps the actual `esptool` flashing logic. | Consumes the `MockEsptoolArgs` object produced by `configure_write_flash_args`. |
| [`esp_flasher/helpers.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/helpers.py) | Provides `open_downloadable_binary` for HTTP downloads. | Called when bootloader or partition files need to be fetched remotely. |
| [`esp_flasher/gui.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/gui.py) | Collects user input (paths, flash size, chip settings). | Passes raw user data to `configure_write_flash_args` for processing. |

## Summary

- **`configure_write_flash_args`** in [`esp_flasher/common.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/common.py) is the central preprocessing function that bridges user firmware selections with ESP hardware requirements.
- The function **detects chip models** (ESP32, ESP32-S3, ESP32-C2, etc.) and validates flash frequencies to ensure hardware compatibility.
- It **resolves file dependencies** by downloading missing bootloaders or partition tables via `open_downloadable_binary` from [`helpers.py`](https://github.com/jason2866/esp_flasher/blob/main/helpers.py).
- The function **maps binaries to memory offsets**, constructing the `addr_filename` list that tells the flasher exactly where to write each component.
- It returns a **MockEsptoolArgs** object that standardizes the interface for [`own_esptool.py`](https://github.com/jason2866/esp_flasher/blob/main/own_esptool.py), enabling consistent flashing across different ESP chip families.

## Frequently Asked Questions

### What does configure_write_flash_args return?

The function returns a **MockEsptoolArgs** object, which is a Python namespace that mimics the command-line arguments structure of the standard `esptool` utility. This object contains attributes including `chip` (target device type), `flash_size`, `addr_filename` (the offset-to-binary mapping), flash mode and frequency settings, and security flags like `secure_pad` and `secure_pad_v2`.

### How does configure_write_flash_args handle missing bootloader files?

When a local bootloader ELF or partition file is not found, the function invokes **format_bootloader_path** or **format_partitions_path** to construct a download URL based on the detected chip model and flash parameters. It then calls **open_downloadable_binary** from [`esp_flasher/helpers.py`](https://github.com/jason2866/esp_flasher/blob/main/esp_flasher/helpers.py) to fetch the file via HTTP. The downloaded binary is read into a `BytesIO` stream and converted from ELF to raw binary format before being added to the flash argument list.

### What is the difference between factory and non-factory image handling?

For **non-factory images**, `configure_write_flash_args` constructs a multi-part `addr_filename` list that includes the bootloader at offset `0x1000`, the partition table at `0x8000`, OTA data at `0xe000`, the safe-boot binary at `0x3f0000`, and the user firmware at its designated offset. For **factory images** (detected via `read_firmware_info`), the function creates a simplified mapping that writes only the single combined firmware binary to address `0x0`, as factory images already contain all necessary components pre-bundled.

### Why does configure_write_flash_args validate flash frequencies?

The function explicitly rejects flash frequencies of **15 MHz, 20 MHz, 26 MHz, and 30 MHz** because the ESP bootloader binaries available in the `jason2866/esp_flasher` repository do not include support for these speeds. This validation occurs after detecting firmware metadata but before resolving file dependencies, preventing hardware communication errors and ensuring the selected bootloader ELF is compatible with the target chip's flash configuration.