Skip to content

Test flashing speed improvements - #1060

Merged
MabezDev merged 14 commits into
esp-rs:mainfrom
SergioGasquez:feat/flashing-speed
Oct 22, 2026
Merged

MabezDev merged 14 commits into
esp-rs:mainfrom
SergioGasquez:feat/flashing-speed

Conversation

@SergioGasquez

@SergioGasquez SergioGasquez commented Aug 4, 2026 •

Copy link
Copy Markdown
Member
  • Update all flasher stubs to esp-flasher-stub v1.4.1
    • The newer stubs improve buffering, support asynchronous flash operations and blank-sector handling, and boost the flash clock on supported chips.
  • Fall back to an uncompressed flash transfer when deflate output would be larger than the original data
  • Strip the stub's 2 status bytes from the GET_SECURITY_INFO payload, so the ESP32-S2 security info is no longer rejected as truncated
  • Report the ROM error code for failed commands instead of Other (0x1)
  • Add regression coverage for the 32-bit FLASH_END and FLASH_DEFL_END payloads required by current stubs

The stub is still uploaded at 115,200 baud, and the requested baud is applied once the stub is running, as esptool does. Raising the ROM loader's baud before the upload corrupts long MEM_DATA packets on USB-to-UART bridges: on an ESP32-C3 behind a CP2102N at 921,600 baud, the 5,880-byte stub text block fails with an invalid CRC (blocks up to 0x800 bytes pass, 0x1000 bytes fail).

Benchmarks

Benchmarked on an ESP32-C6 connected through a CP2102N USB-to-UART adapter, flashing the approximately 1.16 MiB
espflash/tests/data/esp_idf_firmware_c6.elf image with --no-skip. Times are median wall-clock flash-command durations, alternating runs between main and this PR; lower is better.

Scenario main This PR Improvement
921,600 baud, no verification (5 runs) 12.066 s 10.862 s 10.0% faster
921,600 baud, target-side MD5 verification (5 runs) 14.140 s 11.756 s 16.9% faster
Pre-erased flash at 921,600 baud (5 runs) 10.776 s 9.358 s 13.2% faster
115,200 baud, no verification (3 runs) 59.756 s 60.140 s 0.6% slower

At 115,200 baud the newer stub is larger, so most of the improvement is visible at higher baud rates. 921,600 baud is recommended when supported by the adapter and target.

ESP32-S3 and ESP32-C61 (USB-Serial-JTAG)

Benchmarked on an ESP32-S3-DevKitC-1 (v0.2, 8 MB flash) and an ESP32-C61-DevKitC-1 (v1.0, 8 MB flash), both connected through the chip's native USB-Serial-JTAG port, so the requested baud rate (921,600) does not limit throughput. Before every timed run, an untimed step either filled the target region with zeros or erased it. This ensured each run performed a real erase and program instead of rewriting identical data. Times are median wall-clock durations over 5 runs, alternating between main and this PR; lower is better.

  • App: flash --no-skip of the bundled espflash/tests/data/esp32s3 (72 KiB) and esp32c61 (128 KiB) images, including bootloader and partition table
  • 1.16 MiB payload: write-bin 0x10000 of the same ESP-IDF image used above (saved with save-image)
Chip Scenario main This PR Change
ESP32-S3 App, no verification 1.827 s 1.667 s 8.7% faster
ESP32-S3 App, target-side MD5 verification 1.999 s 1.750 s 12.5% faster
ESP32-S3 1.16 MiB payload 13.565 s 9.105 s 32.9% faster
ESP32-S3 1.16 MiB payload, pre-erased flash 11.910 s 6.892 s 42.1% faster
ESP32-C61 App, no verification 1.347 s 1.381 s 2.5% slower
ESP32-C61 App, target-side MD5 verification 1.417 s 1.448 s 2.2% slower
ESP32-C61 1.16 MiB payload 9.031 s 9.012 s 0.2% faster
ESP32-C61 1.16 MiB payload, pre-erased flash 8.059 s 9.192 s 14.1% slower

The ESP32-S3 gains the most. On the ESP32-C61, writes to dirty flash are on par with main, but writes to pre-erased flash are 14% slower. Pre-erased writes with this PR are also slower than dirty writes, which points at the C61 stub's blank-sector handling. Run-to-run spread was below 0.3 s in every scenario.

The ESP32-C61 rows were re-measured with the v1.4.1 stub, which replaced the C61 stub, against main at d6f2551. These runs used release builds with --skip-update-check, so compare their change relative to main rather than their absolute times with the ESP32-S3 rows. Run-to-run spread was below 0.06 s. The v1.4.0 stub gave the same picture (3.8% and 2.6% slower for the app, 0.5% faster on dirty flash, 14.0% slower on pre-erased flash).

@SergioGasquez SergioGasquez changed the title Feat/flashing speed Test flashing speed improvements Aug 4, 2026
@Massimiliano-solutiontech

Massimiliano-solutiontech commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Thanks for refreshing the stubs. The C6 stub_flasher/2 resource in this PR is not byte-identical to the current official ESP Flasher Stub v1.3.0 asset. The official esp32c6.json SHA-256 is a326f564fa8fe3ec69c1c17a9dd2df8918da1e37b44004019a643f5f181b8b27, and v1.2.2 and v1.3.0 ship identical C6 bytes.

A C6-only delta against this PR's head (af82b19) is in bf200cb (branch c6-stub-v1.3.0-on-pr1060 on my fork). It changes only espflash/resources/stubs/esp32c6.toml (entry 0x408011bc; text 6,900 B at 0x40800000; data 216 B at 0x40852f0c).

Why it matters to me: with the v1.3.0 C6 stub, espflash flashes an ESP32-C6 through USB-over-IP passthrough (VirtualHere, SEH UTN) together with the SYNC fix in #1084. With the stub currently on main, the stub never answers over the same link.

@Massimiliano-solutiontech

Copy link
Copy Markdown
Contributor

It's worth waiting the new release? @Dzarda7 added the raise of the CPU freq in the stub-lib espressif/esp-stub-lib#90 (comment)

@SergioGasquez

Copy link
Copy Markdown
Member Author

esp-flasher-stub is already released https://github.com/espressif/esp-flasher-stub/releases/tag/v1.4.0, so I updated it already and updated the benchmarks

@bjoernQ

bjoernQ commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Something like espflash write-bin --baud 921600 0x10000 SOMEFILE fails on this branch for chips other than ESP32,S2,C6
(but 115200 works ofc)

@SergioGasquez

Copy link
Copy Markdown
Member Author

/hil full

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Triggered full HIL for PR #1060.

Revision: 67b3dbcf11c567c16adba8866856c7a9aafad286

Chips: all; suite: full

Run: https://github.com/esp-rs/espflash/actions/runs/37914440184

Status: ❌ HIL run failed (failure).

@SergioGasquez

Copy link
Copy Markdown
Member Author

/hil full

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Triggered full HIL for PR #1060.

Revision: 633c4889df4130b19ad682262f18d324fec991d0

Chips: all; suite: full

Run: https://github.com/esp-rs/espflash/actions/runs/37919481307

Status: ❌ HIL run failed on re-run (attempt 2) (failure).

@SergioGasquez

Copy link
Copy Markdown
Member Author

/hil full

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Triggered full HIL for PR #1060.

Revision: c056bd28829fb35b0119015b8a37b9d5491ccc94

Chips: all; suite: full

Run: https://github.com/esp-rs/espflash/actions/runs/37921912191

Status: ❌ HIL run failed (failure).

@Dzarda7

Dzarda7 commented Oct 9, 2026

Copy link
Copy Markdown

Hi guys, I think we can fix the stub not being able to upload with higher baudrate if you need it, just let me know/open issue. I already considered such feature for our tools too.

@Massimiliano-solutiontech

Copy link
Copy Markdown
Contributor

Hi @Dzarda7 it matters to me because I use a custom tool based on this Rust library to flash devices in our factory, and reducing the flashing time would be very useful. If you need any help with testing or coding, I'd be happy to contribute!

@SergioGasquez

Copy link
Copy Markdown
Member Author

HIL failures are now unrelated.

Hi guys, I think we can fix the stub not being able to upload with higher baudrate if you need it, just let me know/open issue. I already considered such feature for our tools too.

That would be nice, @Massimiliano-solutiontech do you mind opening the issue?

@SergioGasquez

Copy link
Copy Markdown
Member Author

/hil full

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Triggered full HIL for PR #1060.

Revision: 9c7f90128ccadc131097ffc5d5c3cdd78def397d

Chips: all; suite: full

Run: https://github.com/esp-rs/espflash/actions/runs/39747387928

Status: ❌ HIL run failed on re-run (attempt 2) (failure).

@SergioGasquez
SergioGasquez requested a review from bjoernQ October 22, 2026 08:36
esp-flasher-stub boosts the clock on UART for ESP32, ESP32-S2, ESP32-S3,
ESP32-P4, ESP32-S31, ESP32-H4 and ESP32-C6, then reprograms the UART
divider to the baud recorded at ROM init. The ROM's CHANGE_BAUDRATE does
not update that value, so changing baud before uploading the stub leaves
the host at the requested baud while the stub answers at 115,200.

Change baud after the stub is running on all of these chips, not only
ESP32, ESP32-S2 and ESP32-C6.
The GET_SECURITY_INFO payload ends with the status bytes: 4 from the ROM
loader and 2 from the stub. Only the ROM status was stripped, so the
ESP32-S2's 12-byte security info from esp-flasher-stub arrived as 14
bytes and was rejected as a truncated 20-byte response.
v1.4.1 updates esp-stub-lib for ESP32-C61 ECO5, ESP32-P4 ECO8 and the ESP32-C5
160 MHz PLL. Only the ESP32-C5, ESP32-C61 and ESP32-P4 stubs change.
Raising the ROM loader's baud before uploading the stub corrupts long
MEM_DATA packets on USB-to-UART bridges. On an ESP32-C3 behind a CP2102N
at 921,600 baud, the 5,880-byte stub text block fails with an invalid
CRC; blocks up to 0x800 bytes pass and 0x1000 bytes fail.

Upload the stub at the initial baud and change baud once the stub is
running, as esptool does.
Failed commands built the error from the status byte, which is always 1
on failure, so every error showed as "Other (0x1)". Use the error byte,
as sync() already does.
@SergioGasquez

Copy link
Copy Markdown
Member Author

/hil full

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Triggered full HIL for PR #1060.

Revision: 1057939c612b264c1c055dedd07e50016f9e03e9

Chips: all; suite: full

Run: https://github.com/esp-rs/espflash/actions/runs/39755464341

Status: ❌ HIL run failed on re-run (attempt 2) (failure).

@bjoernQ bjoernQ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@MabezDev
MabezDev added this pull request to the merge queue Oct 22, 2026
Merged via the queue into esp-rs:main with commit 515f6cc Oct 22, 2026
25 checks passed
@SergioGasquez
SergioGasquez deleted the feat/flashing-speed branch October 22, 2026 10:28
SergioGasquez added a commit to SergioGasquez/espflash that referenced this pull request Oct 26, 2026
The ESP32-P4 ran a reduced suite because the old esptool flasher stub read
erased flash back as 0x00 in some ranges and reported wrong MD5 checksums
(esp-rs#1037). esp-rs#1060 replaced it with esp-flasher-stub v1.4.1, so run the same
suite as the other chips and drop the tolerance for those erased reads.
SergioGasquez added a commit to SergioGasquez/espflash that referenced this pull request Oct 29, 2026
* test: run the full HIL suite on ESP32-P4

The ESP32-P4 ran a reduced suite because the old esptool flasher stub read
erased flash back as 0x00 in some ranges and reported wrong MD5 checksums
(esp-rs#1037). esp-rs#1060 replaced it with esp-flasher-stub v1.4.1, so run the same
suite as the other chips and drop the tolerance for those erased reads.

* test: flash the ESP32-P4 with a 4 MB image size

With the detected 16 MB in the image, the ESP32-P4 test app drops off USB
right after `cpu_start: Multicore app`, so `flash --monitor` fails with a
broken pipe. The same app boots with espflash's 4 MB default, which the
save-image and write-bin steps already use (esp-rs#1101). Pass it to every
`flash --monitor` step of the flash test, including the QIO one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants