Skip to content
Sourceful Energy

Docs · Hardware

Flashing Zap Firmware

Guide to flashing Sourceful Zap firmware to ESP32 devices using the sequential flasher tool.

Flashing one Zap? Use Flash firmware in your browser. It needs no install and downloads the released images for you. This page covers the batch flasher used in production.

Overview#

The Sourceful Zap flasher is a USB tool for flashing a batch of devices one after the other on a single serial port. For each device it erases the flash, writes the images, resets the device, and reads its serial number and public key from the serial log.

The tool is fw_controller/release/flasher.py in the Zap firmware. It holds no prebuilt images: you bring your own build.

Prerequisites#

  • Python 3
  • USB access to your serial device
  • An ESP32 device with a USB connector, and firmware images built for its board

Installation#

Shell
cd fw_controller/release
python3 -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
pip install -r requirements.txt

Flashing Process#

Pass the images with --files, as address:file:

Shell
B=path/to/your/build
python flasher.py --files \
  0x0:$B/bootloader/bootloader.bin \
  0x8000:$B/partition_table/partition-table.bin \
  0xe000:$B/ota_data_initial.bin \
  0x10000:$B/fw_controller.bin

ota_data_initial.bin makes the Zap boot the first app slot. Without it, and with --no-erase, old OTA data can keep booting the second slot. The bootloader offset 0x0 is for ESP32-C3 and ESP32-S3. ESP32 boards load it from 0x1000.

Available Options#

OptionDescription
--filesImages to flash, as address:file
--build-dirA directory to detect bootloader.bin, partition-table.bin, zap-idf.bin and boot_app0.bin in. An ESP-IDF build of the firmware has other names and subdirectories, so use --files for those
--portSerial port, detected when left out
--list-portsShow available serial ports
--chipForce the chip type: esp32, esp32c3, esp32s2 or esp32s3
--no-eraseSkip the flash erase
--verify-flashVerify flash after writing
--baudrateSerial baudrate, default 115200
--timeoutSerial read timeout in seconds, default 30
--output-baseCustom output file prefix. A timestamp is appended
--debugCheck the setup without flashing
--test-connectionTest the device connection only, with --port

Flashing Workflow#

  1. Connect a device via USB
  2. Flash - The tool erases, flashes the firmware, and resets the device
  3. Extract - It captures the serial number and public key from the serial log
  4. Save - It appends the result to the CSV file
  5. Disconnect the device and connect the next one
  6. Repeat until done (Ctrl+C to stop)

Output Files#

CSV file: <base>_<timestamp>.csv, one row per device that succeeded, with its serial number and public key.

JSON file: <base>_<timestamp>.json, with all results, written when the tool stops.

Troubleshooting#

Permission Issues#

macOS: No additional setup needed

Linux: Add user to dialout group

Shell
sudo usermod -aG dialout $USER
# Then logout and login again

Common Issues#

ProblemSolution
Port busyClose other serial monitors, Arduino IDE
Auto-detect failsUse --port to specify manually
Wrong binary filesUse --debug to check file detection, or pass the images with --files

Debug Commands#

Shell
# Test setup without flashing
python flasher.py --debug

# Test device connection
python flasher.py --test-connection --port /dev/cu.usbmodem101

# List available ports
python flasher.py --list-ports
  • Hardware - Chipsets and the two ways to flash
  • The Zap - What the Zap is and what it does
  • Data Models - Telemetry data model v2: fields, units and signs