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
67 changes: 52 additions & 15 deletions src/esploader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
import { After, Before } from "./types/resetModes.js";
import { FlashFreqValues, FlashModeValues, FlashSizeValues } from "./types/arguments.js";
import { loadFirmwareImage } from "./image/index.js";
import { ROM_LIST } from "./targets/index.js";

/**
* Flash read callback function type
* @param {Uint8Array} packet - Packet data
* @param {number} progress - Progress number
* @param {number} totalSize - Total size number
* Callback function type for handling packets received during flash memory read operations.
* @callback FlashReadCallback
* @param {Uint8Array} packet - The data packet received from the flash memory.
* @param {number} progress - The current progress of the read operation in bytes.
* @param {number} totalSize - The total size of the data to be read in bytes.
*/
export type FlashReadCallback = ((packet: Uint8Array, progress: number, totalSize: number) => void) | null;

Expand Down Expand Up @@ -106,6 +108,8 @@
ESP_FLASH_DEFL_END = 0x12;
ESP_SPI_FLASH_MD5 = 0x13;

ESP_GET_SECURITY_INFO = 0x14;

// Only Stub supported commands
ESP_ERASE_FLASH = 0xd0;
ESP_ERASE_REGION = 0xd1;
Expand Down Expand Up @@ -409,8 +413,9 @@
if (op == null || opRet == op) {
return [val, data];
} else if (data[0] != 0 && data[1] == this.ROM_INVALID_RECV_MSG) {
await this.flushInput();
throw new ESPError("unsupported command error");
this.debug("read_packet unsupported command error " + op);
// await this.flushInput();
throw new ESPError("unsupported command error " + op);
}
}
}
Expand Down Expand Up @@ -649,7 +654,7 @@
this.debug("Connect attempt successful.");
this.info("\n\r", false);

if (detecting) {
if (!detecting) {
const chipMagicValue = (await this.readReg(this.CHIP_DETECT_MAGIC_REG_ADDR)) >>> 0;
this.debug("Chip Magic " + chipMagicValue.toString(16));
const chip = await magic2Chip(chipMagicValue);
Expand All @@ -661,17 +666,46 @@
}
}

/**
* Get the CHIP ID with ESP_GET_SECURITY_INFO check command.
* @returns {number} Chip ID number
*/
async getChipId(): Promise<number | undefined> {
const response = await this.checkCommand("get security info", this.ESP_GET_SECURITY_INFO, new Uint8Array(0));

this.debug("get_chip_id " + response.toString(16));

if (response instanceof Uint8Array && response.length > 16) {
const chipId = response[12] | (response[13] << 8) | (response[14] << 16) | (response[15] << 24);
return chipId;
}
return;
}

/**
* Connect and detect the existing chip.
* @param {string} mode Reset mode to use for connection.
* @param {number} attempts - Number of connection attempts
*/
async detectChip(mode: Before = "default_reset") {
async detectChip(mode: Before = "default_reset", attempts = 7) {
await this.connect(mode);
this.info("Detecting chip type... ", false);
try {
this.info("Detecting chip type... ");
const chipID = await this.getChipId();
for (const cls of ROM_LIST) {
if (chipID === cls.IMAGE_CHIP_ID) {
this.chip = cls;
break;
}
}
} catch (error) {
await this.transport.disconnect();
await this.connect(mode, attempts, false);
}
if (this.chip != null) {
this.info(this.chip.CHIP_NAME);
} else {
this.info("unknown!");
this.info("unknown chip! detectchip has failed.");
}
}

Expand Down Expand Up @@ -1156,11 +1190,14 @@
}

/**
* Read flash memory from the chip.
* @param {number} addr Address number
* @param {number} size Package size
* @param {FlashReadCallback} onPacketReceived Callback function to call when packet is received
* @returns {Uint8Array} Flash read data
* Read data from flash memory of the chip.
* This function reads a specified amount of data from the flash memory starting at a given address.
* It sends a read command to the chip and processes the response packets until the requested size is read.
* @param {number} addr - The starting address in flash memory to read from.
* @param {number} size - The number of bytes to read from flash memory.
* @param {FlashReadCallback} onPacketReceived - Optional callback function to handle each received packet.
* @returns {Promise<Uint8Array>} A promise that resolves to the data read from flash memory as a Uint8Array.
* @throws {ESPError} If the read operation fails or an unexpected response is received.
*/
async readFlash(addr: number, size: number, onPacketReceived: FlashReadCallback = null) {
let pkt = this._appendArray(this._intToByteArray(addr), this._intToByteArray(size));
Expand Down Expand Up @@ -1380,7 +1417,7 @@
const imageObject = await loadFirmwareImage(this.chip, image);
imageObject.verify();
} catch (error) {
console.log(

Check warning on line 1420 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
4 changes: 2 additions & 2 deletions src/image/esp32.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ export class ESP32FirmwareImage extends BaseFirmwareImage {
[this.hdDrv, this.wpDrv] = this.splitByte(hdConfig);

this.chipId = view.getUint8(4);
if (this.chipId !== this.ROM_LOADER.IMAGE_CHIP_ID) {
if (this.ROM_LOADER.IMAGE_CHIP_ID !== undefined && this.chipId !== this.ROM_LOADER.IMAGE_CHIP_ID) {
console.warn(
`Unexpected chip id in image. Expected ${this.ROM_LOADER.IMAGE_CHIP_ID} but value was ${this.chipId}. ` +
"Is this image for a different chip model?",
Expand Down Expand Up @@ -330,7 +330,7 @@ export class ESP32FirmwareImage extends BaseFirmwareImage {
view.setUint8(2, this.joinByte(this.dDrv, this.csDrv));
view.setUint8(3, this.joinByte(this.hdDrv, this.wpDrv));

view.setUint8(4, this.ROM_LOADER.IMAGE_CHIP_ID);
view.setUint8(4, this.ROM_LOADER.IMAGE_CHIP_ID ?? 0);
view.setUint8(5, this.minRev);
view.setUint16(6, this.minRevFull, true);
view.setUint16(8, this.maxRevFull, true);
Expand Down
28 changes: 28 additions & 0 deletions src/targets/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ESP32ROM } from "./esp32";
import { ESP32C2ROM } from "./esp32c2";
import { ESP32C3ROM } from "./esp32c3";
import { ESP32C5ROM } from "./esp32c5";
import { ESP32C6ROM } from "./esp32c6";
import { ESP32C61ROM } from "./esp32c61";
import { ESP32H2ROM } from "./esp32h2";
import { ESP32P4ROM } from "./esp32p4";
import { ESP32S2ROM } from "./esp32s2";
import { ESP32S3ROM } from "./esp32s3";
import { ESP8266ROM } from "./esp8266";

export const CHIP_DEFS = {
esp8266: new ESP8266ROM(),
esp32: new ESP32ROM(),
esp32s2: new ESP32S2ROM(),
esp32s3: new ESP32S3ROM(),
esp32c3: new ESP32C3ROM(),
esp32c2: new ESP32C2ROM(),
esp32c6: new ESP32C6ROM(),
esp32c61: new ESP32C61ROM(),
esp32c5: new ESP32C5ROM(),
esp32h2: new ESP32H2ROM(),
esp32p4: new ESP32P4ROM(),
};

export const CHIP_LIST = Object.keys(CHIP_DEFS) as Array<keyof typeof CHIP_DEFS>;
export const ROM_LIST = Object.values(CHIP_DEFS);
2 changes: 1 addition & 1 deletion src/targets/rom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export abstract class ROM {
// abstract EFUSE_RD_REG_BASE: number; //esp32

abstract FLASH_WRITE_SIZE: number;
// abstract IMAGE_CHIP_ID: number; // not in esp8266
IMAGE_CHIP_ID?: number; // not in esp8266, optional for other chips
abstract SPI_MOSI_DLEN_OFFS: number; // not in esp8266
abstract SPI_MISO_DLEN_OFFS: number; // not in esp8266
abstract SPI_REG_BASE: number;
Expand Down
10 changes: 3 additions & 7 deletions src/webserial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,14 +244,10 @@ class Transport {
}

async flushInput() {
try {
if (!this.reader) {
this.reader = this.device.readable?.getReader();
}
await this.reader?.cancel();
if (this.reader) {
await this.reader.cancel();
this.reader.releaseLock();
this.reader = this.device.readable?.getReader();
} catch (error) {
this.trace(`Error while flushing input: ${error}`);
}
this.buffer = new Uint8Array(0);
}
Expand Down
Loading