Skip to content

Production Programming

Production programming differs from development flashing in one key way: repeatability. Every device must receive identical firmware, be verified, and pass quality checks before shipping. mcesptool provides tools for single-device factory programming, parallel batch operations across multiple ports, and automated quality control.

The esp_factory_program tool runs a complete erase-flash-verify cycle in sequence. It accepts a configuration dict that describes the full firmware stack.

esp_factory_program({
"port": "/dev/ttyUSB0",
"program_config": {
"firmware_path": "/firmware/v2.1/app.bin",
"address": "0x10000",
"bootloader": "/firmware/v2.1/bootloader.bin",
"bootloader_address": "0x1000",
"partition_table": "/firmware/v2.1/partitions.bin",
"partition_table_address": "0x8000",
"erase_before": true,
"verify": true
}
})

The tool executes these steps in order:

  1. Erase the entire flash (when erase_before is true).

  2. Flash the bootloader at the specified address.

  3. Flash the partition table at the specified address.

  4. Flash the application with verification enabled.

The response includes a steps array showing the result of each stage. If any step fails, the operation stops and reports which step failed and why.

If your build produces a single merged binary (bootloader + partitions + app already combined), the config is simpler:

esp_factory_program({
"port": "/dev/ttyUSB0",
"program_config": {
"firmware_path": "/firmware/v2.1/merged.bin",
"address": "0x0",
"erase_before": true,
"verify": true
}
})

When programming multiple devices simultaneously, esp_batch_program runs factory programming in parallel across a list of serial ports.

esp_batch_program({
"device_list": [
"/dev/ttyUSB0",
"/dev/ttyUSB1",
"/dev/ttyUSB2",
"/dev/ttyUSB3"
],
"firmware_path": "/firmware/v2.1/merged.bin"
})

Each device gets the same treatment: full erase, flash at 0x0, and verification. The operations run concurrently using asyncio, so a four-device batch completes in roughly the same time as a single device.

The response reports:

  • total_devices: How many ports were attempted
  • succeeded / failed: Pass/fail counts
  • devices: Per-device results with individual timing and error details

After programming, run esp_quality_control to verify each device is functioning correctly.

The basic test suite runs three fast checks:

esp_quality_control({
"port": "/dev/ttyUSB0",
"test_suite": "basic"
})

Tests performed:

  • Chip identification — confirms the chip responds and reports its type
  • Flash identification — reads flash manufacturer ID and detected size
  • MAC address — reads the factory-programmed MAC

Typical execution time: under 5 seconds.

The response includes a verdict of "PASS" or "FAIL", with individual test results in the tests array. Each test entry includes its own success flag and any error details.

A typical production line sequence:

  1. Connect the device to the programming jig.

  2. Run esp_factory_program with the full firmware stack.

  3. Run esp_quality_control with the "extended" test suite.

  4. If the verdict is "PASS", mark the device as good and record its MAC address.

  5. If "FAIL", flag the device for inspection. The test results indicate which check failed.

See the Production Tools reference for full parameter details.