Skip to content

Commit 914cf51

Browse files
committed
1 parent 92f5836 commit 914cf51

File tree

1 file changed

+13
-178
lines changed

1 file changed

+13
-178
lines changed

docs/janos_flash.html

Lines changed: 13 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,9 @@ <h2>Control</h2>
312312
<option value="development">Development</option>
313313
</select>
314314
<select id="baudSelect" aria-label="Baud rate">
315-
<option value="115200" selected>115200 baud (stable)</option>
315+
<option value="460800">460800 baud</option>
316+
<option value="921600">921600 baud</option>
317+
<option value="115200">115200 baud</option>
316318
</select>
317319
</div>
318320
<div class="status-line">
@@ -324,7 +326,7 @@ <h2>Control</h2>
324326
<strong>Erase</strong> does a full flash erase <span class="mono">(esptool erase-flash)</span> before writing the images.
325327
Only enable it when you have OTA partitions / old firmware and you see bootloops or slot errors.
326328
This web flasher seeds both OTA slots by default by writing the app to <span class="mono">0x20000</span> and <span class="mono">0x410000</span>.
327-
Web flashing is fixed to <span class="mono">115200</span> for reliability. Higher baud changes are currently unstable in <span class="mono">esptool-js</span> over WebSerial on some ESP32-C5 boards.
329+
If the log shows <span class="mono">Flash ID: 0</span> or an MD5 mismatch, reconnect in ROM mode and retry at <span class="mono">115200</span>.
328330
Note: it wipes anything stored in flash (including NVS settings like Wi-Fi creds/config).
329331
</div>
330332
<div class="progress" aria-label="Flash progress">
@@ -387,7 +389,7 @@ <h2>Browser support</h2>
387389
</div>
388390
<footer>
389391
Product of <a href="https://github.com/C5Lab/projectZero/">C5Lab/projectZero</a> -
390-
<span id="pageVersion" class="mono">Web flasher v1.0.10</span>.
392+
<span id="pageVersion" class="mono">Web flasher v1.0.5</span>.
391393
</footer>
392394

393395
<script type="module">
@@ -429,7 +431,6 @@ <h2>Browser support</h2>
429431
isFlashing: false,
430432
autoFlash: false,
431433
autoFlashTriggered: false,
432-
usingStub: null,
433434
monitorPort: null,
434435
monitorReader: null,
435436
monitorWriter: null,
@@ -438,8 +439,7 @@ <h2>Browser support</h2>
438439
monitorConnected: false,
439440
};
440441

441-
const PAGE_VERSION = "1.0.10";
442-
const FLASH_BAUD = 115200;
442+
const PAGE_VERSION = "1.0.5";
443443
const monitorEncoder = new TextEncoder();
444444

445445
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -520,7 +520,8 @@ <h2>Browser support</h2>
520520
monitorLog(`[${time}] ${msg}\n`);
521521
};
522522

523-
const bytesToBinaryString = (bytes) => {
523+
const bufferToBinaryString = (buffer) => {
524+
const bytes = new Uint8Array(buffer);
524525
const chunk = 0x8000;
525526
let result = "";
526527
for (let i = 0; i < bytes.length; i += chunk) {
@@ -529,19 +530,6 @@ <h2>Browser support</h2>
529530
return result;
530531
};
531532

532-
const bufferToBinaryString = (buffer) => bytesToBinaryString(new Uint8Array(buffer));
533-
534-
const padBytesTo = (data, alignment, padCharacter = 0xff) => {
535-
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
536-
const padMod = bytes.length % alignment;
537-
if (padMod === 0) return bytes;
538-
const padding = new Uint8Array(alignment - padMod).fill(padCharacter);
539-
const padded = new Uint8Array(bytes.length + padding.length);
540-
padded.set(bytes, 0);
541-
padded.set(padding, bytes.length);
542-
return padded;
543-
};
544-
545533
const resolveManifestPath = (path) => {
546534
if (!path) return path;
547535
try {
@@ -674,58 +662,6 @@ <h2>Browser support</h2>
674662
}
675663
};
676664

677-
const applyEspToolWorkarounds = (loader) => {
678-
if (!loader || loader.__projectZeroPatched) return;
679-
loader.__projectZeroPatched = true;
680-
681-
const originalRunStub = loader.runStub.bind(loader);
682-
loader.runStub = async () => {
683-
const chipName = loader?.chip?.CHIP_NAME || "";
684-
if (chipName === "ESP32-C5") {
685-
state.usingStub = false;
686-
log("Skipping flasher stub for ESP32-C5. Using ROM bootloader path due to known C5 ECO2 stub flash-write failures.");
687-
return loader.chip;
688-
}
689-
state.usingStub = true;
690-
return originalRunStub();
691-
};
692-
693-
const originalFlashDeflBegin = loader.flashDeflBegin.bind(loader);
694-
loader.flashDeflBegin = async (size, compsize, offset) => {
695-
const chipName = loader?.chip?.CHIP_NAME || "";
696-
if (loader.IS_STUB || chipName === "ESP32" || chipName === "ESP8266") {
697-
return originalFlashDeflBegin(size, compsize, offset);
698-
}
699-
700-
const numBlocks = Math.floor((compsize + loader.FLASH_WRITE_SIZE - 1) / loader.FLASH_WRITE_SIZE);
701-
const eraseBlocks = Math.floor((size + loader.FLASH_WRITE_SIZE - 1) / loader.FLASH_WRITE_SIZE);
702-
const t1 = Date.now();
703-
const writeSize = eraseBlocks * loader.FLASH_WRITE_SIZE;
704-
const timeout = loader.timeoutPerMb(loader.ERASE_REGION_TIMEOUT_PER_MB, writeSize);
705-
706-
loader.info("Compressed " + size + " bytes to " + compsize + "...");
707-
let pkt = loader._appendArray(loader._intToByteArray(writeSize), loader._intToByteArray(numBlocks));
708-
pkt = loader._appendArray(pkt, loader._intToByteArray(loader.FLASH_WRITE_SIZE));
709-
pkt = loader._appendArray(pkt, loader._intToByteArray(offset));
710-
pkt = loader._appendArray(pkt, loader._intToByteArray(0));
711-
712-
await loader.checkCommand(
713-
"enter compressed flash mode",
714-
loader.ESP_FLASH_DEFL_BEGIN,
715-
pkt,
716-
undefined,
717-
undefined,
718-
timeout,
719-
);
720-
721-
if (size !== 0) {
722-
const elapsed = Date.now() - t1;
723-
loader.info("Took " + elapsed / 1000 + "." + (elapsed % 1000) + "s to erase flash block");
724-
}
725-
return numBlocks;
726-
};
727-
};
728-
729665
const connect = async () => {
730666
ensureSupport();
731667
if (state.connected) {
@@ -750,7 +686,7 @@ <h2>Browser support</h2>
750686
try {
751687
state.port.addEventListener("disconnect", state.onDisconnect);
752688
} catch {}
753-
const baud = FLASH_BAUD;
689+
const baud = parseInt(ui.baud.value, 10);
754690
state.transport = new Transport(state.port, true);
755691
const loaderOptions = {
756692
transport: state.transport,
@@ -762,9 +698,6 @@ <h2>Browser support</h2>
762698
},
763699
debugLogging: false,
764700
};
765-
if ((parseInt(ui.baud.value, 10) || FLASH_BAUD) !== FLASH_BAUD) {
766-
log(`Selected baud overridden to stable ${FLASH_BAUD} for WebSerial flashing.`);
767-
}
768701
setStatus(`Syncing with chip (hold BOOT + RESET). Timeout ${Math.round(CONNECT_TIMEOUT_MS/1000)}s`);
769702
log("Syncing with chip");
770703

@@ -775,8 +708,6 @@ <h2>Browser support</h2>
775708
attempt += 1;
776709
try {
777710
state.esploader = new ESPLoader(loaderOptions);
778-
state.usingStub = null;
779-
applyEspToolWorkarounds(state.esploader);
780711
log("Connecting...");
781712
state.chip = await state.esploader.main();
782713
lastErr = null;
@@ -862,93 +793,11 @@ <h2>Browser support</h2>
862793
log(`Fetching ${url} @ 0x${part.offset.toString(16)}`);
863794
const { buf, usedUrl } = await resolveAssetUrl(url);
864795
log(`Fetched ${usedUrl}`);
865-
files.push({ data: bufferToBinaryString(buf), bytes: new Uint8Array(buf), address: part.offset });
796+
files.push({ data: bufferToBinaryString(buf), address: part.offset });
866797
}
867798
return files;
868799
};
869800

870-
const writeFlashViaRom = async (loader, files, flashOptions) => {
871-
if (!loader) throw new Error("ESP loader is not ready");
872-
873-
loader.info("Using uncompressed ROM flash path for ESP32-C5 to avoid compressed-flash failures.");
874-
875-
if (flashOptions.flashSize && flashOptions.flashSize !== "keep") {
876-
const flashEnd = loader.flashSizeBytes(flashOptions.flashSize);
877-
for (let i = 0; i < files.length; i += 1) {
878-
const size = files[i]?.bytes?.length ?? files[i]?.data?.length ?? 0;
879-
if (size + files[i].address > flashEnd) {
880-
throw new Error(`File ${i + 1} doesn't fit in the available flash`);
881-
}
882-
}
883-
}
884-
885-
for (let i = 0; i < files.length; i += 1) {
886-
let image = files[i].bytes instanceof Uint8Array
887-
? new Uint8Array(files[i].bytes)
888-
: loader.bstrToUi8(files[i].data || "");
889-
890-
if (image.length === 0) continue;
891-
892-
image = padBytesTo(image, 4);
893-
const address = files[i].address;
894-
image = await loader._updateImageFlashParams(
895-
image,
896-
address,
897-
flashOptions.flashMode,
898-
flashOptions.flashFreq,
899-
flashOptions.flashSize,
900-
);
901-
902-
const calcmd5 = flashOptions.calculateMD5Hash
903-
? String(flashOptions.calculateMD5Hash(bytesToBinaryString(image)))
904-
: null;
905-
906-
const totalBytes = image.length;
907-
const blocks = await loader.flashBegin(totalBytes, address);
908-
let seq = 0;
909-
let imageOffset = 0;
910-
let timeout = loader.DEFAULT_TIMEOUT || 3000;
911-
if (flashOptions.reportProgress) flashOptions.reportProgress(i, 0, totalBytes);
912-
913-
const t1 = Date.now();
914-
while (imageOffset < image.length) {
915-
const blockSize = Math.min(loader.FLASH_WRITE_SIZE, image.length - imageOffset);
916-
const block = image.slice(imageOffset, imageOffset + blockSize);
917-
const pct = Math.min(100, Math.floor((100 * (seq + 1)) / Math.max(blocks, 1)));
918-
loader.info(`Writing at 0x${(address + imageOffset).toString(16)}... (${pct}%)`);
919-
920-
if (typeof loader.timeoutPerMb === "function") {
921-
timeout = Math.max(loader.DEFAULT_TIMEOUT || 3000, loader.timeoutPerMb(loader.ERASE_WRITE_TIMEOUT_PER_MB, block.length));
922-
}
923-
924-
await loader.flashBlock(block, seq, timeout);
925-
imageOffset += blockSize;
926-
seq += 1;
927-
928-
if (flashOptions.reportProgress) {
929-
flashOptions.reportProgress(i, imageOffset, totalBytes);
930-
}
931-
}
932-
933-
await loader.flashFinish(false, timeout);
934-
935-
const elapsedSeconds = ((Date.now() - t1) / 1000).toFixed(3);
936-
loader.info(`Wrote ${totalBytes} bytes at 0x${address.toString(16)} in ${elapsedSeconds} seconds.`);
937-
938-
if (calcmd5) {
939-
loader.info("File md5: " + calcmd5);
940-
const flashMd5 = await loader.flashMd5sum(address, totalBytes);
941-
loader.info("Flash md5: " + flashMd5);
942-
if (String(flashMd5) !== calcmd5) {
943-
throw new Error("MD5 of file does not match data in flash!");
944-
}
945-
loader.info("Hash of data verified.");
946-
}
947-
}
948-
949-
loader.info("Leaving...");
950-
};
951-
952801
const flash = async () => {
953802
ensureSupport();
954803
if (!state.esploader) {
@@ -960,20 +809,12 @@ <h2>Browser support</h2>
960809
ui.progress.style.width = "0%";
961810
try {
962811
const files = await fetchFiles();
963-
const flashingFromStub = state.usingStub !== false;
964-
setStatus(flashingFromStub ? "Uploading stub and flashing" : "Flashing from ROM bootloader");
812+
setStatus("Uploading stub and flashing");
965813
log("Preparing flash writes");
966-
if (!flashingFromStub) {
967-
log("ROM bootloader mode active. Stub is disabled for ESP32-C5 compatibility.");
968-
if (ui.eraseAll?.checked) {
969-
setStatus("ROM bootloader will erase only the regions being flashed.");
970-
log("Erase-all requested, but ESP32-C5 ROM mode cannot use stub-only full-chip erase. Proceeding with per-region erase during flash begin.");
971-
}
972-
}
973814
const flashOptions = {
974815
fileArray: files,
975816
flashSize: "8MB",
976-
eraseAll: flashingFromStub && !!ui.eraseAll?.checked,
817+
eraseAll: !!ui.eraseAll?.checked,
977818
compress: true,
978819
reportProgress: (fileIndex, written, total) => {
979820
const pct = Math.min(100, Math.round((written / total) * 100));
@@ -982,13 +823,7 @@ <h2>Browser support</h2>
982823
},
983824
calculateMD5Hash: (image) => CryptoJS.MD5(CryptoJS.enc.Latin1.parse(image)),
984825
};
985-
const romChipName = state.esploader?.chip?.CHIP_NAME || "";
986-
if (!flashingFromStub && romChipName === "ESP32-C5") {
987-
log("Using uncompressed ROM flash path for ESP32-C5 to bypass FLASH_DEFL failures in esptool-js.");
988-
await writeFlashViaRom(state.esploader, files, flashOptions);
989-
} else {
990-
await state.esploader.writeFlash(flashOptions);
991-
}
826+
await state.esploader.writeFlash(flashOptions);
992827
await state.esploader.after();
993828
ui.progress.style.width = "100%";
994829
setStatus("Flash complete. Press RESET if the board doesn't reboot.");

0 commit comments

Comments
 (0)