Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/typescript/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ <h3> Program </h3>
<input class="btn btn-info btn-sm" type="button" id="copyTraceButton" value="Copy Trace" />
<input class="btn btn-warning btn-sm" type="button" id="disconnectButton" value="Disconnect" />
<input class="btn btn-danger btn-sm" type="button" id="eraseButton" value="Erase Flash" />
<input class="btn btn-success btn-sm" type="button" id="flashAndMonitorButton" value="Flash & Monitor" />
<br>

<div class="alert alert-danger alert-dismissible" id="alertDiv" style="display:none; margin-top:10px">
Expand Down
107 changes: 101 additions & 6 deletions examples/typescript/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
const eraseButton = document.getElementById("eraseButton") as HTMLButtonElement;
const addFileButton = document.getElementById("addFile") as HTMLButtonElement;
const programButton = document.getElementById("programButton");
const flashAndMonitorButton = document.getElementById("flashAndMonitorButton") as HTMLButtonElement;
const filesDiv = document.getElementById("files");
const terminal = document.getElementById("terminal");
const programDiv = document.getElementById("program");
Expand Down Expand Up @@ -46,6 +47,7 @@
eraseButton.style.display = "none";
consoleStopButton.style.display = "none";
resetButton.style.display = "none";
flashAndMonitorButton.style.display = "none";
filesDiv.style.display = "none";

/**
Expand Down Expand Up @@ -103,18 +105,20 @@

// Temporarily broken
// await esploader.flashId();
console.log("Settings done for :" + chip);

Check warning on line 108 in examples/typescript/src/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
lblBaudrate.style.display = "none";
lblConnTo.innerHTML = "Connected to device: " + chip;
lblConsoleFor.innerHTML = "Connected to device: " + chip;
lblConnTo.style.display = "block";
baudrates.style.display = "none";
connectButton.style.display = "none";
disconnectButton.style.display = "initial";
eraseButton.style.display = "initial";
flashAndMonitorButton.style.display = "initial";
filesDiv.style.display = "initial";
consoleDiv.style.display = "none";
} catch (e) {
console.error(e);

Check warning on line 121 in examples/typescript/src/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
term.writeln(`Error: ${e.message}`);
}
};
Expand All @@ -138,7 +142,7 @@
try {
await esploader.eraseFlash();
} catch (e) {
console.error(e);

Check warning on line 145 in examples/typescript/src/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
term.writeln(`Error: ${e.message}`);
} finally {
eraseButton.disabled = false;
Expand Down Expand Up @@ -211,6 +215,7 @@
device = null;
transport = null;
chip = null;
esploader = null;
}

disconnectButton.onclick = async () => {
Expand All @@ -224,6 +229,7 @@
disconnectButton.style.display = "none";
traceButton.style.display = "none";
eraseButton.style.display = "none";
flashAndMonitorButton.style.display = "none";
lblConnTo.style.display = "none";
filesDiv.style.display = "none";
alertDiv.style.display = "none";
Expand All @@ -238,6 +244,13 @@
transport = new Transport(device, true);
}
lblConsoleFor.style.display = "block";
if (device) {
const deviceINFO = await device.getInfo();
const info = `WebSerial VendorID 0x${deviceINFO.usbVendorId.toString(
16,
)} ProductID 0x${deviceINFO.usbProductId.toString(16)}`;
lblConsoleFor.innerHTML = "Connected to device: " + info;
}
lblConsoleBaudrate.style.display = "none";
consoleBaudrates.style.display = "none";
consoleStartButton.style.display = "none";
Expand All @@ -257,15 +270,23 @@
}
term.write(value);
}
console.log("quitting console");

Check warning on line 273 in examples/typescript/src/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
};

consoleStopButton.onclick = async () => {
isConsoleClosed = true;
if (transport) {
await transport.disconnect();
await transport.waitForUnlock(1500);
try {
if (esploader) {
await esploader.stopConsoleMonitoring();
} else if (transport) {
await transport.disconnect();
await transport.waitForUnlock(1500);
}
} catch (e) {
console.error(e);

Check warning on line 286 in examples/typescript/src/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
term.writeln(`Error: ${e.message}`);
}

term.reset();
lblConsoleBaudrate.style.display = "initial";
consoleBaudrates.style.display = "initial";
Expand All @@ -274,6 +295,17 @@
resetButton.style.display = "none";
lblConsoleFor.style.display = "none";
programDiv.style.display = "initial";
if (esploader) {
connectButton.style.display = "initial";
disconnectButton.style.display = "none";
traceButton.style.display = "none";
eraseButton.style.display = "none";
flashAndMonitorButton.style.display = "none";
lblConnTo.style.display = "none";
filesDiv.style.display = "none";
alertDiv.style.display = "none";
consoleDiv.style.display = "initial";
}
cleanUp();
};

Expand Down Expand Up @@ -318,8 +350,6 @@
alertDiv.style.display = "block";
return;
}

// Hide error message
alertDiv.style.display = "none";

const fileArray = [];
Expand Down Expand Up @@ -356,10 +386,9 @@
await esploader.writeFlash(flashOptions);
await esploader.after();
} catch (e) {
console.error(e);

Check warning on line 389 in examples/typescript/src/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
term.writeln(`Error: ${e.message}`);
} finally {
// Hide progress bars and show erase buttons
for (let index = 1; index < table.rows.length; index++) {
table.rows[index].cells[2].style.display = "none";
table.rows[index].cells[3].style.display = "initial";
Expand All @@ -368,3 +397,69 @@
};

addFileButton.onclick(this);

// Flash and Monitor button handler
flashAndMonitorButton.onclick = async () => {
const alertMsg = document.getElementById("alertmsg");
const err = validateProgramInputs();

if (err != "success") {
alertMsg.innerHTML = "<strong>" + err + "</strong>";
alertDiv.style.display = "block";
return;
}

alertDiv.style.display = "none";

const fileArray = [];
const progressBars = [];

for (let index = 1; index < table.rows.length; index++) {
const row = table.rows[index];

const offSetObj = row.cells[0].childNodes[0] as HTMLInputElement;
const offset = parseInt(offSetObj.value);

const fileObj = row.cells[1].childNodes[0] as ChildNode & { data: string };
const progressBar = row.cells[2].childNodes[0];

progressBar.textContent = "0";
progressBars.push(progressBar);

row.cells[2].style.display = "initial";
row.cells[3].style.display = "none";

fileArray.push({ data: fileObj.data, address: offset });
}

try {
const flashOptions: FlashOptions = {
fileArray: fileArray,
eraseAll: false,
compress: true,
reportProgress: (fileIndex, written, total) => {
progressBars[fileIndex].value = (written / total) * 100;
},
calculateMD5Hash: (image) => CryptoJS.MD5(CryptoJS.enc.Latin1.parse(image)),
} as FlashOptions;

await esploader.flashAndMonitor(flashOptions, "hard_reset", false, parseInt(consoleBaudrates.value));

programDiv.style.display = "none";
consoleDiv.style.display = "initial";
lblConsoleFor.style.display = "block";
lblConsoleBaudrate.style.display = "none";
consoleBaudrates.style.display = "none";
consoleStartButton.style.display = "none";
consoleStopButton.style.display = "initial";
resetButton.style.display = "initial";
} catch (e) {
console.error(e);

Check warning on line 457 in examples/typescript/src/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
term.writeln(`Error: ${e.message}`);
} finally {
for (let index = 1; index < table.rows.length; index++) {
table.rows[index].cells[2].style.display = "none";
table.rows[index].cells[3].style.display = "initial";
}
}
};
79 changes: 79 additions & 0 deletions src/esploader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1380,7 +1380,7 @@
const imageObject = await loadFirmwareImage(this.chip, image);
imageObject.verify();
} catch (error) {
console.log(

Check warning on line 1383 in src/esploader.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
`Warning: Image file at 0x${address.toString(16)} is not a valid ${
this.chip.CHIP_NAME
} image, so not changing any flash settings.`,
Expand Down Expand Up @@ -1594,6 +1594,85 @@
}
}

/**
* Flash the device and then start monitoring the console output.
* @param {FlashOptions} flashOptions - Flash options for writing to flash
* @param {After} afterMode - Reset mode after flashing
* @param {boolean} usingUsbOtg - Whether using USB-OTG for hard reset
* @param {number} monitorBaudrate - Baudrate for console monitoring (default: 115200)
* @param {Function} onData - Optional callback function to handle received data
* @returns {Promise<void>}
*/
async flashAndMonitor(
flashOptions: FlashOptions,
afterMode: After = "hard_reset",
usingUsbOtg?: boolean,
monitorBaudrate = 115200,
onData?: (data: Uint8Array) => void,
): Promise<void> {
// First perform the flash operation
this.info("Starting flashing...");
await this.writeFlash(flashOptions);
this.info("Flashing completed. Starting reset...");
await this.after(afterMode, usingUsbOtg);

// Start monitoring after a brief delay to allow the device to boot
await this._sleep(1000);

this.info("Starting console monitoring...");
this.startConsoleMonitoring(monitorBaudrate, onData); // Don't await this to allow continuous monitoring
}

/**
* Start monitoring the console output from the device.
* @param {number} baudrate - Baudrate for console monitoring
* @param {Function} onData - Optional callback function to handle received data
* @returns {Promise<void>}
*/
async startConsoleMonitoring(baudrate = 115200, onData?: (data: Uint8Array) => void): Promise<void> {
try {
await this.transport.disconnect();
await this.transport.connect(baudrate, this.serialOptions);

this.info(`Console monitoring started at ${baudrate} baud`);

let isMonitoring = true;
while (isMonitoring) {
const readLoop = this.transport.rawRead();
const { value, done } = await readLoop.next();

if (done || !value) {
isMonitoring = false;
} else {
if (this.terminal) {
// Write raw Uint8Array to terminal to preserve ANSI escape codes
this.terminal.write(this.ui8ToBstr(value));
}
if (onData) {
onData(value);
}
}
}
} catch (error) {
this.error(`Console monitoring error: ${error}`);
throw error;
}
}

/**
* Stop console monitoring and disconnect.
* @returns {Promise<void>}
*/
async stopConsoleMonitoring(): Promise<void> {
try {
await this.transport.disconnect();
await this.transport.waitForUnlock(1500);
this.info("Console monitoring stopped");
} catch (error) {
this.error(`Error stopping console monitoring: ${error}`);
}
}

/**
* Read SPI flash manufacturer and device id.
*/
Expand Down
Loading