diff --git a/src/esploader.ts b/src/esploader.ts index c74132ac..3fb3defe 100644 --- a/src/esploader.ts +++ b/src/esploader.ts @@ -11,12 +11,14 @@ import { FlashOptions } from "./types/flashOptions.js"; 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; @@ -106,6 +108,8 @@ export class ESPLoader { 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; @@ -409,8 +413,9 @@ export class ESPLoader { 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); } } } @@ -649,7 +654,7 @@ export class ESPLoader { 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); @@ -661,17 +666,46 @@ export class ESPLoader { } } + /** + * Get the CHIP ID with ESP_GET_SECURITY_INFO check command. + * @returns {number} Chip ID number + */ + async getChipId(): Promise { + 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."); } } @@ -1156,11 +1190,14 @@ export class ESPLoader { } /** - * 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} 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)); diff --git a/src/image/esp32.ts b/src/image/esp32.ts index 3d526252..69e1162e 100644 --- a/src/image/esp32.ts +++ b/src/image/esp32.ts @@ -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?", @@ -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); diff --git a/src/targets/index.ts b/src/targets/index.ts new file mode 100644 index 00000000..3af90a13 --- /dev/null +++ b/src/targets/index.ts @@ -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; +export const ROM_LIST = Object.values(CHIP_DEFS); diff --git a/src/targets/rom.ts b/src/targets/rom.ts index 5b4d040c..ca0688b4 100644 --- a/src/targets/rom.ts +++ b/src/targets/rom.ts @@ -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; diff --git a/src/webserial.ts b/src/webserial.ts index 14bd6fc3..6d8ffab3 100644 --- a/src/webserial.ts +++ b/src/webserial.ts @@ -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); }