import { ROM } from "./rom.js"; export class ESP8266ROM extends ROM { constructor() { super(...arguments); this.CHIP_NAME = "ESP8266"; this.CHIP_DETECT_MAGIC_VALUE = [0xfff0c101]; this.EFUSE_RD_REG_BASE = 0x3ff00050; this.UART_CLKDIV_REG = 0x60000014; this.UART_CLKDIV_MASK = 0xfffff; this.XTAL_CLK_DIVIDER = 2; this.FLASH_WRITE_SIZE = 0x4000; // NOT IMPLEMENTED, SETTING EMPTY VALUE this.BOOTLOADER_FLASH_OFFSET = 0; this.UART_DATE_REG_ADDR = 0; this.FLASH_SIZES = { "512KB": 0x00, "256KB": 0x10, "1MB": 0x20, "2MB": 0x30, "4MB": 0x40, "2MB-c1": 0x50, "4MB-c1": 0x60, "8MB": 0x80, "16MB": 0x90, }; this.SPI_REG_BASE = 0x60000200; this.SPI_USR_OFFS = 0x1c; this.SPI_USR1_OFFS = 0x20; this.SPI_USR2_OFFS = 0x24; this.SPI_MOSI_DLEN_OFFS = 0; // not in esp8266 this.SPI_MISO_DLEN_OFFS = 0; // not in esp8266 this.SPI_W0_OFFS = 0x40; this.getChipFeatures = async (loader) => { const features = ["WiFi"]; if ((await this.getChipDescription(loader)) == "ESP8285") features.push("Embedded Flash"); return features; }; } async readEfuse(loader, offset) { const addr = this.EFUSE_RD_REG_BASE + 4 * offset; loader.debug("Read efuse " + addr); return await loader.readReg(addr); } async getChipDescription(loader) { const efuse3 = await this.readEfuse(loader, 2); const efuse0 = await this.readEfuse(loader, 0); const is8285 = ((efuse0 & (1 << 4)) | (efuse3 & (1 << 16))) != 0; // One or the other efuse bit is set for ESP8285 return is8285 ? "ESP8285" : "ESP8266EX"; } async getCrystalFreq(loader) { const uartDiv = (await loader.readReg(this.UART_CLKDIV_REG)) & this.UART_CLKDIV_MASK; const etsXtal = (loader.transport.baudrate * uartDiv) / 1000000 / this.XTAL_CLK_DIVIDER; let normXtal; if (etsXtal > 33) { normXtal = 40; } else { normXtal = 26; } if (Math.abs(normXtal - etsXtal) > 1) { loader.info("WARNING: Detected crystal freq " + etsXtal + "MHz is quite different to normalized freq " + normXtal + "MHz. Unsupported crystal in use?"); } return normXtal; } _d2h(d) { const h = (+d).toString(16); return h.length === 1 ? "0" + h : h; } async readMac(loader) { let mac0 = await this.readEfuse(loader, 0); mac0 = mac0 >>> 0; let mac1 = await this.readEfuse(loader, 1); mac1 = mac1 >>> 0; let mac3 = await this.readEfuse(loader, 3); mac3 = mac3 >>> 0; const mac = new Uint8Array(6); if (mac3 != 0) { mac[0] = (mac3 >> 16) & 0xff; mac[1] = (mac3 >> 8) & 0xff; mac[2] = mac3 & 0xff; } else if (((mac1 >> 16) & 0xff) == 0) { mac[0] = 0x18; mac[1] = 0xfe; mac[2] = 0x34; } else if (((mac1 >> 16) & 0xff) == 1) { mac[0] = 0xac; mac[1] = 0xd0; mac[2] = 0x74; } else { loader.error("Unknown OUI"); } mac[3] = (mac1 >> 8) & 0xff; mac[4] = mac1 & 0xff; mac[5] = (mac0 >> 24) & 0xff; return (this._d2h(mac[0]) + ":" + this._d2h(mac[1]) + ":" + this._d2h(mac[2]) + ":" + this._d2h(mac[3]) + ":" + this._d2h(mac[4]) + ":" + this._d2h(mac[5])); } getEraseSize(offset, size) { return size; } }