-
Notifications
You must be signed in to change notification settings - Fork 151
Description
Checklist
- Checked the issue tracker for similar issues to ensure this is not a duplicate
- Read the documentation to confirm the issue is not addressed there and your configuration is set correctly
- Tested with the latest version to ensure the issue hasn't been fixed
How often does this bug occurs?
always
Expected behavior
The flashMode, flashFreq, and flashSize options should be applied to configure the SPI flash regardless of whether the bootloader image header can be parsed.
When the warning "Image file at 0x2000 doesn't look like an image file" occurs, the library should fall back to using the user-provided flash settings instead of skipping flash configuration entirely.
Actual behavior (suspected bug)
When using esptool-js to flash an ESP32-P4 device, the flashMode, flashFreq, and flashSize options passed to writeFlash() are ignored. The library outputs a warning indicating it cannot recognize the bootloader as a valid image file, and consequently does not apply the required flash settings. This results in a device that appears to flash successfully but fails to boot.
The same firmware files flash correctly using the Python esptool with explicit --flash-mode dio --flash-freq 80m --flash-size 32MB flags.
Error logs or terminal output
esptool.js
Serial port WebSerial VendorID 0x1a86 ProductID 0x55d3
Connecting...
Detecting chip type...
ESP32-P4
Chip is ESP32-P4 (revision v1.0)
Features: High-Performance MCU
Crystal is 40MHz
MAC: 30:ed:a0:e2:08:69
Uploading stub...
Running stub...
Stub running...
Changing baudrate to 460800
Changed
Warning: Image file at 0x2000 doesn't look like an image file, so not changing any flash settings.
Compressed 23584 bytes to 14454...
Writing at 0x2000... (100%)
Wrote 23584 bytes (14454 compressed) at 0x2000 in 0.666 seconds.
Hash of data verified.
[...continues for all files...]Steps to reproduce the behavior
1. Prepare firmware files
Standard ESP-IDF build output for ESP32-P4:
bootloader.bin(23,584 bytes) → address 0x2000partition-table.bin(3,072 bytes) → address 0x8000ota_data_initial.bin(8,192 bytes) → address 0x10000app.bin(~1.7 MB) → address 0x20000
2. Flash using esptool-js
import { ESPLoader, Transport } from "https://unpkg.com/[email protected]/bundle.js";
const device = await navigator.serial.requestPort({});
const transport = new Transport(device, true);
const esploader = new ESPLoader({ transport, baudrate: 460800 });
await esploader.main();
const flashOptions = {
fileArray: [
{ data: bootloaderBinaryString, address: 0x2000 },
{ data: partitionTableBinaryString, address: 0x8000 },
{ data: otaDataBinaryString, address: 0x10000 },
{ data: appBinaryString, address: 0x20000 }
],
flashSize: "32MB",
flashMode: "dio",
flashFreq: "80m",
eraseAll: false,
compress: true
};
await esploader.writeFlash(flashOptions);3. Observe console output
esptool.js
Serial port WebSerial VendorID 0x1a86 ProductID 0x55d3
Connecting...
Detecting chip type...
ESP32-P4
Chip is ESP32-P4 (revision v1.0)
Features: High-Performance MCU
Crystal is 40MHz
MAC: 30:ed:a0:e2:08:69
Uploading stub...
Running stub...
Stub running...
Changing baudrate to 460800
Changed
Warning: Image file at 0x2000 doesn't look like an image file, so not changing any flash settings.
Compressed 23584 bytes to 14454...
Writing at 0x2000... (100%)
Wrote 23584 bytes (14454 compressed) at 0x2000 in 0.666 seconds.
Hash of data verified.
[...continues for all files...]
4. Result
- All files appear to write successfully
- Device does not boot after flashing
- Screen remains black, no serial output
Project release version
0.5.7
System architecture
Intel/AMD 64-bit (modern PC, older Mac)
Operating system
Windows
Operating system version
Windows 11
Shell
PowerShell
Additional context
esptool-js Bug Report: ESP32-P4 Flash Settings Not Applied
Repository: https://github.com/espressif/esptool-js
esptool-js version: 0.5.7
Affected chip: ESP32-P4
Summary
When using esptool-js to flash an ESP32-P4 device, the flashMode, flashFreq, and flashSize options passed to writeFlash() are ignored. The library outputs a warning indicating it cannot recognize the bootloader as a valid image file, and consequently does not apply the required flash settings. This results in a device that appears to flash successfully but fails to boot.
The same firmware files flash correctly using the Python esptool with explicit --flash-mode dio --flash-freq 80m --flash-size 32MB flags.
Environment
- esptool-js version: 0.5.7 (via unpkg CDN)
- Browser: Google Chrome 131, Microsoft Edge 131
- Operating System: Windows 10/11
- Target chip: ESP32-P4 (revision v1.0)
- Board: Waveshare ESP32-P4-WIFI6-Touch-LCD-4B
- Flash: 32MB, DIO mode required, 80MHz
Steps to Reproduce
1. Prepare firmware files
Standard ESP-IDF build output for ESP32-P4:
bootloader.bin(23,584 bytes) → address 0x2000partition-table.bin(3,072 bytes) → address 0x8000ota_data_initial.bin(8,192 bytes) → address 0x10000app.bin(~1.7 MB) → address 0x20000
2. Flash using esptool-js
import { ESPLoader, Transport } from "https://unpkg.com/[email protected]/bundle.js";
const device = await navigator.serial.requestPort({});
const transport = new Transport(device, true);
const esploader = new ESPLoader({ transport, baudrate: 460800 });
await esploader.main();
const flashOptions = {
fileArray: [
{ data: bootloaderBinaryString, address: 0x2000 },
{ data: partitionTableBinaryString, address: 0x8000 },
{ data: otaDataBinaryString, address: 0x10000 },
{ data: appBinaryString, address: 0x20000 }
],
flashSize: "32MB",
flashMode: "dio",
flashFreq: "80m",
eraseAll: false,
compress: true
};
await esploader.writeFlash(flashOptions);3. Observe console output
esptool.js
Serial port WebSerial VendorID 0x1a86 ProductID 0x55d3
Connecting...
Detecting chip type...
ESP32-P4
Chip is ESP32-P4 (revision v1.0)
Features: High-Performance MCU
Crystal is 40MHz
MAC: 30:ed:a0:e2:08:69
Uploading stub...
Running stub...
Stub running...
Changing baudrate to 460800
Changed
Warning: Image file at 0x2000 doesn't look like an image file, so not changing any flash settings.
Compressed 23584 bytes to 14454...
Writing at 0x2000... (100%)
Wrote 23584 bytes (14454 compressed) at 0x2000 in 0.666 seconds.
Hash of data verified.
[...continues for all files...]
4. Result
- All files appear to write successfully
- Device does not boot after flashing
- Screen remains black, no serial output
Expected Behavior
The flashMode, flashFreq, and flashSize options should be applied to configure the SPI flash regardless of whether the bootloader image header can be parsed.
When the warning "Image file at 0x2000 doesn't look like an image file" occurs, the library should fall back to using the user-provided flash settings instead of skipping flash configuration entirely.
Working Workaround (Python esptool)
The same files flash correctly using Python esptool:
python -m esptool --chip esp32p4 -p COM5 -b 460800 \
--before default_reset --after hard_reset \
write_flash --flash-mode dio --flash-freq 80m --flash-size 32MB --force \
0x2000 bootloader.bin \
0x8000 partition-table.bin \
0x10000 ota_data_initial.bin \
0x20000 app.binThe device boots successfully after this command.
Root Cause Analysis
Bootloader Header Inspection
The ESP32-P4 bootloader has a valid ESP image header:
First 8 bytes: e9 03 02 5f da 9e f2 4f
│ │ │ │
│ │ │ └─ Flash size/freq: 0x5f = 32MB (5) + 80MHz (f)
│ │ └──── Flash mode: 0x02 = DIO
│ └─────── Segment count: 3
└────────── Magic byte: 0xE9 ✓
The bootloader header already contains correct flash settings (DIO, 32MB, 80MHz). However, esptool-js reports it "doesn't look like an image file."
Suspected Issue
The updateImageFlashParams() function in esptool-js may have ESP32-P4-specific header parsing that fails, possibly due to:
- Different header structure for ESP32-P4 bootloader
- Missing ESP32-P4 chip family in image validation logic
- Stricter validation that rejects valid ESP32-P4 images
When image parsing fails, the code path that calls flash_set_parameters() with user-provided settings is not executed.
Suggested Fix
When the image header cannot be parsed, the library should:
- Apply user-provided flash settings if
flashMode,flashFreq, orflashSizeare explicitly passed - Log a warning that settings are being applied without image header validation
- Continue with the write operation using the user's settings
Example pseudocode:
if (!canParseImageHeader(data, address)) {
if (userProvidedFlashSettings) {
console.warn(`Using user-provided flash settings for address ${address}`);
await this.flashSetParameters(userFlashMode, userFlashFreq, userFlashSize);
} else {
console.warn(`Cannot detect flash settings for ${address}, using defaults`);
}
}Additional Information
Verified Data Integrity
- SHA256 hashes of files match between working CLI flash and non-working JS flash
- File sizes are identical
- Binary string conversion verified correct
Files Available
A complete reproduction case with firmware files is available at:
https://github.com/fabkury/p3a
Impact
This issue prevents browser-based flashing for all ESP32-P4 projects, requiring users to install Python and use command-line tools instead of the more accessible web-based approach.
Related
- ESP32-P4 is a relatively new chip (2024)
- esptool-js added ESP32-P4 target support in
src/targets/esp32p4.ts - Python esptool handles ESP32-P4 correctly with explicit flags
Contact
- Reporter: @fabkury
- Project: p3a (Physical Pixel Art Player)
- Repository: https://github.com/fabkury/p3a