tasmota-webserial-esptool 7.0.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/esp_loader.ts CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  } from "./const";
63
63
  import { getStubCode } from "./stubs";
64
64
  import { hexFormatter, sleep, slipEncode, toHex } from "./util";
65
- // @ts-ignore
65
+ // @ts-expect-error pako ESM module doesn't have proper type definitions
66
66
  import { deflate } from "pako/dist/pako.esm.mjs";
67
67
  import { pack, unpack } from "./struct";
68
68
 
@@ -140,6 +140,7 @@ export class ESPLoader extends EventTarget {
140
140
  },
141
141
  0x303a: {
142
142
  // Espressif (native USB)
143
+ 0x2: { name: "ESP32-S2 Native USB", maxBaudrate: 2000000 },
143
144
  0x1001: { name: "ESP32 Native USB", maxBaudrate: 2000000 },
144
145
  0x1002: { name: "ESP32 Native USB", maxBaudrate: 2000000 },
145
146
  0x4002: { name: "ESP32 Native USB", maxBaudrate: 2000000 },
@@ -192,8 +193,8 @@ export class ESPLoader extends EventTarget {
192
193
  await this.detectChip();
193
194
 
194
195
  // Read the OTP data for this chip and store into this.efuses array
195
- let FlAddr = getSpiFlashAddresses(this.getChipFamily());
196
- let AddrMAC = FlAddr.macFuse;
196
+ const FlAddr = getSpiFlashAddresses(this.getChipFamily());
197
+ const AddrMAC = FlAddr.macFuse;
197
198
  for (let i = 0; i < 4; i++) {
198
199
  this._efuses[i] = await this.readRegister(AddrMAC + 4 * i);
199
200
  }
@@ -240,10 +241,10 @@ export class ESPLoader extends EventTarget {
240
241
  this.logger.debug(
241
242
  `Unknown IMAGE_CHIP_ID: ${chipId}, falling back to magic value detection`,
242
243
  );
243
- } catch (err) {
244
+ } catch (error) {
244
245
  // GET_SECURITY_INFO not supported, fall back to magic value detection
245
246
  this.logger.debug(
246
- `GET_SECURITY_INFO failed, using magic value detection: ${err}`,
247
+ `GET_SECURITY_INFO failed, using magic value detection: ${error}`,
247
248
  );
248
249
 
249
250
  // Clear input buffer and re-sync to recover from failed command
@@ -261,8 +262,8 @@ export class ESPLoader extends EventTarget {
261
262
  }
262
263
 
263
264
  // Fallback: Use magic value detection for ESP8266, ESP32, ESP32-S2, and ESP32-P4 RC versions
264
- let chipMagicValue = await this.readRegister(CHIP_DETECT_MAGIC_REG_ADDR);
265
- let chip = CHIP_DETECT_MAGIC_VALUES[chipMagicValue >>> 0];
265
+ const chipMagicValue = await this.readRegister(CHIP_DETECT_MAGIC_REG_ADDR);
266
+ const chip = CHIP_DETECT_MAGIC_VALUES[chipMagicValue >>> 0];
266
267
  if (chip === undefined) {
267
268
  throw new Error(
268
269
  `Unknown Chip: Hex: ${toHex(
@@ -324,7 +325,7 @@ export class ESPLoader extends EventTarget {
324
325
  chipId: number;
325
326
  apiVersion: number;
326
327
  }> {
327
- const [_, responseData] = await this.checkCommand(
328
+ const [, responseData] = await this.checkCommand(
328
329
  ESP_GET_SECURITY_INFO,
329
330
  [],
330
331
  0,
@@ -376,10 +377,12 @@ export class ESPLoader extends EventTarget {
376
377
  this._reader = this.port.readable!.getReader();
377
378
 
378
379
  try {
379
- while (true) {
380
+ let keepReading = true;
381
+ while (keepReading) {
380
382
  const { value, done } = await this._reader.read();
381
383
  if (done) {
382
384
  this._reader.releaseLock();
385
+ keepReading = false;
383
386
  break;
384
387
  }
385
388
  if (!value || value.length === 0) {
@@ -394,8 +397,8 @@ export class ESPLoader extends EventTarget {
394
397
  // Track total bytes read from serial port
395
398
  this._totalBytesRead += value.length;
396
399
  }
397
- } catch (err) {
398
- console.error("Read loop got disconnected");
400
+ } catch {
401
+ this.logger.error("Read loop got disconnected");
399
402
  }
400
403
  // Disconnected!
401
404
  this.connected = false;
@@ -473,11 +476,11 @@ export class ESPLoader extends EventTarget {
473
476
  * The MAC address burned into the OTP memory of the ESP chip
474
477
  */
475
478
  macAddr() {
476
- let macAddr = new Array(6).fill(0);
477
- let mac0 = this._efuses[0];
478
- let mac1 = this._efuses[1];
479
- let mac2 = this._efuses[2];
480
- let mac3 = this._efuses[3];
479
+ const macAddr = new Array(6).fill(0);
480
+ const mac0 = this._efuses[0];
481
+ const mac1 = this._efuses[1];
482
+ const mac2 = this._efuses[2];
483
+ const mac3 = this._efuses[3];
481
484
  let oui;
482
485
  if (this.chipFamily == CHIP_FAMILY_ESP8266) {
483
486
  if (mac3 != 0) {
@@ -533,9 +536,9 @@ export class ESPLoader extends EventTarget {
533
536
  if (this.debug) {
534
537
  this.logger.debug("Reading from Register " + toHex(reg, 8));
535
538
  }
536
- let packet = pack("<I", reg);
539
+ const packet = pack("<I", reg);
537
540
  await this.sendCommand(ESP_READ_REG, packet);
538
- let [val, _data] = await this.getResponse(ESP_READ_REG);
541
+ const [val] = await this.getResponse(ESP_READ_REG);
539
542
  return val;
540
543
  }
541
544
 
@@ -553,12 +556,13 @@ export class ESPLoader extends EventTarget {
553
556
  ): Promise<[number, number[]]> {
554
557
  timeout = Math.min(timeout, MAX_TIMEOUT);
555
558
  await this.sendCommand(opcode, buffer, checksum);
556
- let [value, data] = await this.getResponse(opcode, timeout);
559
+ const [value, responseData] = await this.getResponse(opcode, timeout);
557
560
 
558
- if (data === null) {
561
+ if (responseData === null) {
559
562
  throw new Error("Didn't get enough status bytes");
560
563
  }
561
564
 
565
+ let data = responseData;
562
566
  let statusLen = 0;
563
567
 
564
568
  if (this.IS_STUB || this.chipFamily == CHIP_FAMILY_ESP8266) {
@@ -594,7 +598,7 @@ export class ESPLoader extends EventTarget {
594
598
  if (data.length < statusLen) {
595
599
  throw new Error("Didn't get enough status bytes");
596
600
  }
597
- let status = data.slice(-statusLen, data.length);
601
+ const status = data.slice(-statusLen, data.length);
598
602
  data = data.slice(0, -statusLen);
599
603
  if (this.debug) {
600
604
  this.logger.debug("status", status);
@@ -618,7 +622,7 @@ export class ESPLoader extends EventTarget {
618
622
  * does not check response
619
623
  */
620
624
  async sendCommand(opcode: number, buffer: number[], checksum = 0) {
621
- let packet = slipEncode([
625
+ const packet = slipEncode([
622
626
  ...pack("<BBHI", 0x00, opcode, buffer.length, checksum),
623
627
  ...buffer,
624
628
  ]);
@@ -642,7 +646,7 @@ export class ESPLoader extends EventTarget {
642
646
  let inEscape = false;
643
647
  let readBytes: number[] = [];
644
648
  while (true) {
645
- let stamp = Date.now();
649
+ const stamp = Date.now();
646
650
  readBytes = [];
647
651
  while (Date.now() - stamp < timeout) {
648
652
  if (this._inputBuffer.length > 0) {
@@ -654,14 +658,14 @@ export class ESPLoader extends EventTarget {
654
658
  }
655
659
  }
656
660
  if (readBytes.length == 0) {
657
- let waitingFor = partialPacket === null ? "header" : "content";
661
+ const waitingFor = partialPacket === null ? "header" : "content";
658
662
  throw new SlipReadError("Timed out waiting for packet " + waitingFor);
659
663
  }
660
664
  if (this.debug)
661
665
  this.logger.debug(
662
666
  "Read " + readBytes.length + " bytes: " + hexFormatter(readBytes),
663
667
  );
664
- for (let b of readBytes) {
668
+ for (const b of readBytes) {
665
669
  if (partialPacket === null) {
666
670
  // waiting for packet header
667
671
  if (b == 0xc0) {
@@ -737,7 +741,7 @@ export class ESPLoader extends EventTarget {
737
741
  continue;
738
742
  }
739
743
 
740
- const [resp, opRet, _lenRet, val] = unpack("<BBHI", packet.slice(0, 8));
744
+ const [resp, opRet, , val] = unpack("<BBHI", packet.slice(0, 8));
741
745
  if (resp != 1) {
742
746
  continue;
743
747
  }
@@ -758,7 +762,7 @@ export class ESPLoader extends EventTarget {
758
762
  * Calculate checksum of a blob, as it is defined by the ROM
759
763
  */
760
764
  checksum(data: number[], state = ESP_CHECKSUM_MAGIC) {
761
- for (let b of data) {
765
+ for (const b of data) {
762
766
  state ^= b;
763
767
  }
764
768
  return state;
@@ -771,10 +775,10 @@ export class ESPLoader extends EventTarget {
771
775
 
772
776
  try {
773
777
  // Send ESP_ROM_BAUD(115200) as the old one if running STUB otherwise 0
774
- let buffer = pack("<II", baud, this.IS_STUB ? ESP_ROM_BAUD : 0);
778
+ const buffer = pack("<II", baud, this.IS_STUB ? ESP_ROM_BAUD : 0);
775
779
  await this.checkCommand(ESP_CHANGE_BAUDRATE, buffer);
776
780
  } catch (e) {
777
- console.error(e);
781
+ this.logger.error(`Baudrate change error: ${e}`);
778
782
  throw new Error(
779
783
  `Unable to change the baud rate to ${baud}: No response from set baud rate command.`,
780
784
  );
@@ -827,7 +831,7 @@ export class ESPLoader extends EventTarget {
827
831
  // Restart Readloop
828
832
  this.readLoop();
829
833
  } catch (e) {
830
- console.error(e);
834
+ this.logger.error(`Reconfigure port error: ${e}`);
831
835
  throw new Error(`Unable to change the baud rate to ${baud}: ${e}`);
832
836
  }
833
837
  }
@@ -840,7 +844,7 @@ export class ESPLoader extends EventTarget {
840
844
  async sync() {
841
845
  for (let i = 0; i < 5; i++) {
842
846
  this._inputBuffer.length = 0;
843
- let response = await this._sync();
847
+ const response = await this._sync();
844
848
  if (response) {
845
849
  await sleep(SYNC_TIMEOUT);
846
850
  return true;
@@ -860,11 +864,11 @@ export class ESPLoader extends EventTarget {
860
864
  await this.sendCommand(ESP_SYNC, SYNC_PACKET);
861
865
  for (let i = 0; i < 8; i++) {
862
866
  try {
863
- let [_reply, data] = await this.getResponse(ESP_SYNC, SYNC_TIMEOUT);
867
+ const [, data] = await this.getResponse(ESP_SYNC, SYNC_TIMEOUT);
864
868
  if (data.length > 1 && data[0] == 0 && data[1] == 0) {
865
869
  return true;
866
870
  }
867
- } catch (err) {
871
+ } catch {
868
872
  // If read packet fails.
869
873
  }
870
874
  }
@@ -897,10 +901,10 @@ export class ESPLoader extends EventTarget {
897
901
  ) {
898
902
  if (binaryData.byteLength >= 8) {
899
903
  // unpack the (potential) image header
900
- var header = Array.from(new Uint8Array(binaryData, 0, 4));
901
- let headerMagic = header[0];
902
- let headerFlashMode = header[2];
903
- let headerFlashSizeFreq = header[3];
904
+ const header = Array.from(new Uint8Array(binaryData, 0, 4));
905
+ const headerMagic = header[0];
906
+ const headerFlashMode = header[2];
907
+ const headerFlashSizeFreq = header[3];
904
908
 
905
909
  this.logger.log(
906
910
  `Image header, Magic=${toHex(headerMagic)}, FlashMode=${toHex(
@@ -909,7 +913,7 @@ export class ESPLoader extends EventTarget {
909
913
  );
910
914
  }
911
915
 
912
- let uncompressedFilesize = binaryData.byteLength;
916
+ const uncompressedFilesize = binaryData.byteLength;
913
917
  let compressedFilesize = 0;
914
918
 
915
919
  let dataToFlash;
@@ -938,10 +942,10 @@ export class ESPLoader extends EventTarget {
938
942
  let seq = 0;
939
943
  let written = 0;
940
944
  let position = 0;
941
- let stamp = Date.now();
942
- let flashWriteSize = this.getFlashWriteSize();
945
+ const stamp = Date.now();
946
+ const flashWriteSize = this.getFlashWriteSize();
943
947
 
944
- let filesize = compress ? compressedFilesize : uncompressedFilesize;
948
+ const filesize = compress ? compressedFilesize : uncompressedFilesize;
945
949
 
946
950
  while (filesize - position > 0) {
947
951
  if (this.debug) {
@@ -1027,8 +1031,7 @@ export class ESPLoader extends EventTarget {
1027
1031
  await this.flushSerialBuffers();
1028
1032
 
1029
1033
  let eraseSize;
1030
- let buffer;
1031
- let flashWriteSize = this.getFlashWriteSize();
1034
+ const flashWriteSize = this.getFlashWriteSize();
1032
1035
  if (
1033
1036
  !this.IS_STUB &&
1034
1037
  [
@@ -1049,22 +1052,19 @@ export class ESPLoader extends EventTarget {
1049
1052
  ) {
1050
1053
  await this.checkCommand(ESP_SPI_ATTACH, new Array(8).fill(0));
1051
1054
  }
1052
- let numBlocks = Math.floor((size + flashWriteSize - 1) / flashWriteSize);
1055
+ const numBlocks = Math.floor((size + flashWriteSize - 1) / flashWriteSize);
1053
1056
  if (this.chipFamily == CHIP_FAMILY_ESP8266) {
1054
1057
  eraseSize = this.getEraseSize(offset, size);
1055
1058
  } else {
1056
1059
  eraseSize = size;
1057
1060
  }
1058
1061
 
1059
- let timeout;
1060
- if (this.IS_STUB) {
1061
- timeout = DEFAULT_TIMEOUT;
1062
- } else {
1063
- timeout = timeoutPerMb(ERASE_REGION_TIMEOUT_PER_MB, size);
1064
- }
1062
+ const timeout = this.IS_STUB
1063
+ ? DEFAULT_TIMEOUT
1064
+ : timeoutPerMb(ERASE_REGION_TIMEOUT_PER_MB, size);
1065
1065
 
1066
- let stamp = Date.now();
1067
- buffer = pack("<IIII", eraseSize, numBlocks, flashWriteSize, offset);
1066
+ const stamp = Date.now();
1067
+ let buffer = pack("<IIII", eraseSize, numBlocks, flashWriteSize, offset);
1068
1068
  if (
1069
1069
  this.chipFamily == CHIP_FAMILY_ESP32 ||
1070
1070
  this.chipFamily == CHIP_FAMILY_ESP32S2 ||
@@ -1108,22 +1108,18 @@ export class ESPLoader extends EventTarget {
1108
1108
  *
1109
1109
  */
1110
1110
 
1111
- async flashDeflBegin(
1112
- size = 0,
1113
- compressedSize = 0,
1114
- offset = 0,
1115
- encrypted = false,
1116
- ) {
1111
+ async flashDeflBegin(size = 0, compressedSize = 0, offset = 0) {
1117
1112
  // Start downloading compressed data to Flash (performs an erase)
1118
1113
  // Returns number of blocks to write.
1119
- let flashWriteSize = this.getFlashWriteSize();
1120
- let numBlocks = Math.floor(
1114
+ const flashWriteSize = this.getFlashWriteSize();
1115
+ const numBlocks = Math.floor(
1121
1116
  (compressedSize + flashWriteSize - 1) / flashWriteSize,
1122
1117
  );
1123
- let eraseBlocks = Math.floor((size + flashWriteSize - 1) / flashWriteSize);
1118
+ const eraseBlocks = Math.floor(
1119
+ (size + flashWriteSize - 1) / flashWriteSize,
1120
+ );
1124
1121
  let writeSize = 0;
1125
1122
  let timeout = 0;
1126
- let buffer;
1127
1123
 
1128
1124
  if (this.IS_STUB) {
1129
1125
  writeSize = size; // stub expects number of bytes here, manages erasing internally
@@ -1132,7 +1128,7 @@ export class ESPLoader extends EventTarget {
1132
1128
  writeSize = eraseBlocks * flashWriteSize; // ROM expects rounded up to erase block size
1133
1129
  timeout = DEFAULT_TIMEOUT;
1134
1130
  }
1135
- buffer = pack("<IIII", writeSize, numBlocks, flashWriteSize, offset);
1131
+ const buffer = pack("<IIII", writeSize, numBlocks, flashWriteSize, offset);
1136
1132
 
1137
1133
  await this.checkCommand(ESP_FLASH_DEFL_BEGIN, buffer, 0, timeout);
1138
1134
 
@@ -1140,24 +1136,24 @@ export class ESPLoader extends EventTarget {
1140
1136
  }
1141
1137
 
1142
1138
  async flashFinish() {
1143
- let buffer = pack("<I", 1);
1139
+ const buffer = pack("<I", 1);
1144
1140
  await this.checkCommand(ESP_FLASH_END, buffer);
1145
1141
  }
1146
1142
 
1147
1143
  async flashDeflFinish() {
1148
- let buffer = pack("<I", 1);
1144
+ const buffer = pack("<I", 1);
1149
1145
  await this.checkCommand(ESP_FLASH_DEFL_END, buffer);
1150
1146
  }
1151
1147
 
1152
1148
  getBootloaderOffset() {
1153
- let bootFlashOffs = getSpiFlashAddresses(this.getChipFamily());
1154
- let BootldrFlashOffs = bootFlashOffs.flashOffs;
1149
+ const bootFlashOffs = getSpiFlashAddresses(this.getChipFamily());
1150
+ const BootldrFlashOffs = bootFlashOffs.flashOffs;
1155
1151
  return BootldrFlashOffs;
1156
1152
  }
1157
1153
 
1158
1154
  async flashId() {
1159
- let SPIFLASH_RDID = 0x9f;
1160
- let result = await this.runSpiFlashCommand(SPIFLASH_RDID, [], 24);
1155
+ const SPIFLASH_RDID = 0x9f;
1156
+ const result = await this.runSpiFlashCommand(SPIFLASH_RDID, [], 24);
1161
1157
  return result;
1162
1158
  }
1163
1159
 
@@ -1175,7 +1171,7 @@ export class ESPLoader extends EventTarget {
1175
1171
  let buffer = pack("<IIII", address, value, mask, delayUs);
1176
1172
  if (delayAfterUs > 0) {
1177
1173
  // add a dummy write to a date register as an excuse to have a delay
1178
- buffer.concat(
1174
+ buffer = buffer.concat(
1179
1175
  pack(
1180
1176
  "<IIII",
1181
1177
  getSpiFlashAddresses(this.getChipFamily()).uartDateReg,
@@ -1195,8 +1191,10 @@ export class ESPLoader extends EventTarget {
1195
1191
  ) {
1196
1192
  if (spiAddresses.mosiDlenOffs != -1) {
1197
1193
  // ESP32/32S2/32S3/32C3 has a more sophisticated way to set up "user" commands
1198
- let SPI_MOSI_DLEN_REG = spiAddresses.regBase + spiAddresses.mosiDlenOffs;
1199
- let SPI_MISO_DLEN_REG = spiAddresses.regBase + spiAddresses.misoDlenOffs;
1194
+ const SPI_MOSI_DLEN_REG =
1195
+ spiAddresses.regBase + spiAddresses.mosiDlenOffs;
1196
+ const SPI_MISO_DLEN_REG =
1197
+ spiAddresses.regBase + spiAddresses.misoDlenOffs;
1200
1198
  if (mosiBits > 0) {
1201
1199
  await this.writeRegister(SPI_MOSI_DLEN_REG, mosiBits - 1);
1202
1200
  }
@@ -1204,19 +1202,19 @@ export class ESPLoader extends EventTarget {
1204
1202
  await this.writeRegister(SPI_MISO_DLEN_REG, misoBits - 1);
1205
1203
  }
1206
1204
  } else {
1207
- let SPI_DATA_LEN_REG = spiAddresses.regBase + spiAddresses.usr1Offs;
1208
- let SPI_MOSI_BITLEN_S = 17;
1209
- let SPI_MISO_BITLEN_S = 8;
1210
- let mosiMask = mosiBits == 0 ? 0 : mosiBits - 1;
1211
- let misoMask = misoBits == 0 ? 0 : misoBits - 1;
1212
- let value =
1205
+ const SPI_DATA_LEN_REG = spiAddresses.regBase + spiAddresses.usr1Offs;
1206
+ const SPI_MOSI_BITLEN_S = 17;
1207
+ const SPI_MISO_BITLEN_S = 8;
1208
+ const mosiMask = mosiBits == 0 ? 0 : mosiBits - 1;
1209
+ const misoMask = misoBits == 0 ? 0 : misoBits - 1;
1210
+ const value =
1213
1211
  (misoMask << SPI_MISO_BITLEN_S) | (mosiMask << SPI_MOSI_BITLEN_S);
1214
1212
  await this.writeRegister(SPI_DATA_LEN_REG, value);
1215
1213
  }
1216
1214
  }
1217
1215
  async waitDone(spiCmdReg: number, spiCmdUsr: number) {
1218
1216
  for (let i = 0; i < 10; i++) {
1219
- let cmdValue = await this.readRegister(spiCmdReg);
1217
+ const cmdValue = await this.readRegister(spiCmdReg);
1220
1218
  if ((cmdValue & spiCmdUsr) == 0) {
1221
1219
  return;
1222
1220
  }
@@ -1240,23 +1238,23 @@ export class ESPLoader extends EventTarget {
1240
1238
  // reads back 'read_bits' of reply on MISO. Result is a number.
1241
1239
 
1242
1240
  // SPI_USR register flags
1243
- let SPI_USR_COMMAND = 1 << 31;
1244
- let SPI_USR_MISO = 1 << 28;
1245
- let SPI_USR_MOSI = 1 << 27;
1241
+ const SPI_USR_COMMAND = 1 << 31;
1242
+ const SPI_USR_MISO = 1 << 28;
1243
+ const SPI_USR_MOSI = 1 << 27;
1246
1244
 
1247
1245
  // SPI registers, base address differs ESP32* vs 8266
1248
- let spiAddresses = getSpiFlashAddresses(this.getChipFamily());
1249
- let base = spiAddresses.regBase;
1250
- let SPI_CMD_REG = base;
1251
- let SPI_USR_REG = base + spiAddresses.usrOffs;
1252
- let SPI_USR2_REG = base + spiAddresses.usr2Offs;
1253
- let SPI_W0_REG = base + spiAddresses.w0Offs;
1246
+ const spiAddresses = getSpiFlashAddresses(this.getChipFamily());
1247
+ const base = spiAddresses.regBase;
1248
+ const SPI_CMD_REG = base;
1249
+ const SPI_USR_REG = base + spiAddresses.usrOffs;
1250
+ const SPI_USR2_REG = base + spiAddresses.usr2Offs;
1251
+ const SPI_W0_REG = base + spiAddresses.w0Offs;
1254
1252
 
1255
1253
  // SPI peripheral "command" bitmasks for SPI_CMD_REG
1256
- let SPI_CMD_USR = 1 << 18;
1254
+ const SPI_CMD_USR = 1 << 18;
1257
1255
 
1258
1256
  // shift values
1259
- let SPI_USR2_COMMAND_LEN_SHIFT = 28;
1257
+ const SPI_USR2_COMMAND_LEN_SHIFT = 28;
1260
1258
 
1261
1259
  if (readBits > 32) {
1262
1260
  throw new Error(
@@ -1269,9 +1267,9 @@ export class ESPLoader extends EventTarget {
1269
1267
  );
1270
1268
  }
1271
1269
 
1272
- let dataBits = data.length * 8;
1273
- let oldSpiUsr = await this.readRegister(SPI_USR_REG);
1274
- let oldSpiUsr2 = await this.readRegister(SPI_USR2_REG);
1270
+ const dataBits = data.length * 8;
1271
+ const oldSpiUsr = await this.readRegister(SPI_USR_REG);
1272
+ const oldSpiUsr2 = await this.readRegister(SPI_USR2_REG);
1275
1273
 
1276
1274
  let flags = SPI_USR_COMMAND;
1277
1275
 
@@ -1292,9 +1290,10 @@ export class ESPLoader extends EventTarget {
1292
1290
  if (dataBits == 0) {
1293
1291
  await this.writeRegister(SPI_W0_REG, 0); // clear data register before we read it
1294
1292
  } else {
1295
- data.concat(new Array(data.length % 4).fill(0x00)); // pad to 32-bit multiple
1293
+ const padLen = (4 - (data.length % 4)) % 4;
1294
+ data = data.concat(new Array(padLen).fill(0x00)); // pad to 32-bit multiple
1296
1295
 
1297
- let words = unpack("I".repeat(Math.floor(data.length / 4)), data);
1296
+ const words = unpack("I".repeat(Math.floor(data.length / 4)), data);
1298
1297
  let nextReg = SPI_W0_REG;
1299
1298
 
1300
1299
  this.logger.debug(`Words Length: ${words.length}`);
@@ -1310,7 +1309,7 @@ export class ESPLoader extends EventTarget {
1310
1309
  await this.writeRegister(SPI_CMD_REG, SPI_CMD_USR);
1311
1310
  await this.waitDone(SPI_CMD_REG, SPI_CMD_USR);
1312
1311
 
1313
- let status = await this.readRegister(SPI_W0_REG);
1312
+ const status = await this.readRegister(SPI_W0_REG);
1314
1313
  // restore some SPI controller registers
1315
1314
  await this.writeRegister(SPI_USR_REG, oldSpiUsr);
1316
1315
  await this.writeRegister(SPI_USR2_REG, oldSpiUsr2);
@@ -1319,9 +1318,9 @@ export class ESPLoader extends EventTarget {
1319
1318
  async detectFlashSize() {
1320
1319
  this.logger.log("Detecting Flash Size");
1321
1320
 
1322
- let flashId = await this.flashId();
1323
- let manufacturer = flashId & 0xff;
1324
- let flashIdLowbyte = (flashId >> 16) & 0xff;
1321
+ const flashId = await this.flashId();
1322
+ const manufacturer = flashId & 0xff;
1323
+ const flashIdLowbyte = (flashId >> 16) & 0xff;
1325
1324
 
1326
1325
  this.logger.log(`FlashId: ${toHex(flashId)}`);
1327
1326
  this.logger.log(`Flash Manufacturer: ${manufacturer.toString(16)}`);
@@ -1341,10 +1340,10 @@ export class ESPLoader extends EventTarget {
1341
1340
  * Provides a workaround for the bootloader erase bug on ESP8266.
1342
1341
  */
1343
1342
  getEraseSize(offset: number, size: number) {
1344
- let sectorsPerBlock = 16;
1345
- let sectorSize = FLASH_SECTOR_SIZE;
1346
- let numSectors = Math.floor((size + sectorSize - 1) / sectorSize);
1347
- let startSector = Math.floor(offset / sectorSize);
1343
+ const sectorsPerBlock = 16;
1344
+ const sectorSize = FLASH_SECTOR_SIZE;
1345
+ const numSectors = Math.floor((size + sectorSize - 1) / sectorSize);
1346
+ const startSector = Math.floor(offset / sectorSize);
1348
1347
 
1349
1348
  let headSectors = sectorsPerBlock - (startSector % sectorsPerBlock);
1350
1349
  if (numSectors < headSectors) {
@@ -1396,16 +1395,13 @@ export class ESPLoader extends EventTarget {
1396
1395
  * ignore errors.
1397
1396
  */
1398
1397
  async memFinish(entrypoint = 0) {
1399
- let timeout = this.IS_STUB ? DEFAULT_TIMEOUT : MEM_END_ROM_TIMEOUT;
1400
- let data = pack("<II", entrypoint == 0 ? 1 : 0, entrypoint);
1398
+ const timeout = this.IS_STUB ? DEFAULT_TIMEOUT : MEM_END_ROM_TIMEOUT;
1399
+ const data = pack("<II", entrypoint == 0 ? 1 : 0, entrypoint);
1401
1400
  return await this.checkCommand(ESP_MEM_END, data, 0, timeout);
1402
1401
  }
1403
1402
 
1404
1403
  async runStub(skipFlashDetection = false): Promise<EspStubLoader> {
1405
- const stub: Record<string, any> | null = await getStubCode(
1406
- this.chipFamily,
1407
- this.chipRevision,
1408
- );
1404
+ const stub = await getStubCode(this.chipFamily, this.chipRevision);
1409
1405
 
1410
1406
  // No stub available for this chip, return ROM loader
1411
1407
  if (stub === null) {
@@ -1416,32 +1412,29 @@ export class ESPLoader extends EventTarget {
1416
1412
  }
1417
1413
 
1418
1414
  // We're transferring over USB, right?
1419
- let ramBlock = USB_RAM_BLOCK;
1415
+ const ramBlock = USB_RAM_BLOCK;
1420
1416
 
1421
1417
  // Upload
1422
1418
  this.logger.log("Uploading stub...");
1423
- for (let field of ["text", "data"]) {
1424
- if (Object.keys(stub).includes(field)) {
1425
- let offset = stub[field + "_start"];
1426
- let length = stub[field].length;
1427
- let blocks = Math.floor((length + ramBlock - 1) / ramBlock);
1428
- await this.memBegin(length, blocks, ramBlock, offset);
1429
- for (let seq of Array(blocks).keys()) {
1430
- let fromOffs = seq * ramBlock;
1431
- let toOffs = fromOffs + ramBlock;
1432
- if (toOffs > length) {
1433
- toOffs = length;
1434
- }
1435
- await this.memBlock(stub[field].slice(fromOffs, toOffs), seq);
1419
+ for (const field of ["text", "data"] as const) {
1420
+ const fieldData = stub[field];
1421
+ const offset = stub[`${field}_start` as "text_start" | "data_start"];
1422
+ const length = fieldData.length;
1423
+ const blocks = Math.floor((length + ramBlock - 1) / ramBlock);
1424
+ await this.memBegin(length, blocks, ramBlock, offset);
1425
+ for (const seq of Array(blocks).keys()) {
1426
+ const fromOffs = seq * ramBlock;
1427
+ let toOffs = fromOffs + ramBlock;
1428
+ if (toOffs > length) {
1429
+ toOffs = length;
1436
1430
  }
1431
+ await this.memBlock(fieldData.slice(fromOffs, toOffs), seq);
1437
1432
  }
1438
1433
  }
1439
- await this.memFinish(stub["entry"]);
1440
-
1441
- let pChar: string;
1434
+ await this.memFinish(stub.entry);
1442
1435
 
1443
1436
  const p = await this.readPacket(500);
1444
- pChar = String.fromCharCode(...p);
1437
+ const pChar = String.fromCharCode(...p);
1445
1438
 
1446
1439
  if (pChar != "OHAI") {
1447
1440
  throw new Error("Failed to start stub. Unexpected response: " + pChar);
@@ -1463,7 +1456,7 @@ export class ESPLoader extends EventTarget {
1463
1456
  try {
1464
1457
  writer.releaseLock();
1465
1458
  } catch (err) {
1466
- console.error("Ignoring release lock error", err);
1459
+ this.logger.error(`Ignoring release lock error: ${err}`);
1467
1460
  }
1468
1461
  }
1469
1462
 
@@ -1707,8 +1700,8 @@ export class ESPLoader extends EventTarget {
1707
1700
  );
1708
1701
 
1709
1702
  // Send read flash command for this chunk
1710
- let pkt = pack("<IIII", currentAddr, chunkSize, 0x1000, 1024);
1711
- const [res, _] = await this.checkCommand(ESP_READ_FLASH, pkt);
1703
+ const pkt = pack("<IIII", currentAddr, chunkSize, 0x1000, 1024);
1704
+ const [res] = await this.checkCommand(ESP_READ_FLASH, pkt);
1712
1705
 
1713
1706
  if (res != 0) {
1714
1707
  throw new Error("Failed to read memory: " + res);
@@ -1797,7 +1790,7 @@ export class ESPLoader extends EventTarget {
1797
1790
  remainingSize -= chunkSize;
1798
1791
 
1799
1792
  this.logger.debug(
1800
- `Total progress: 0x${allData.length.toString(16)}/0x${size.toString(16)} bytes`,
1793
+ `Total progress: 0x${allData.length.toString(16)} from 0x${size.toString(16)} bytes`,
1801
1794
  );
1802
1795
  }
1803
1796
 
@@ -1819,27 +1812,26 @@ class EspStubLoader extends ESPLoader {
1819
1812
  */
1820
1813
  async memBegin(
1821
1814
  size: number,
1822
- blocks: number,
1823
- blocksize: number,
1815
+ _blocks: number,
1816
+ _blocksize: number,
1824
1817
  offset: number,
1825
- ): Promise<any> {
1826
- let stub = await getStubCode(this.chipFamily, this.chipRevision);
1818
+ ): Promise<[number, number[]]> {
1819
+ const stub = await getStubCode(this.chipFamily, this.chipRevision);
1827
1820
 
1828
1821
  // Stub may be null for chips without stub support
1829
1822
  if (stub === null) {
1830
- return;
1823
+ return [0, []];
1831
1824
  }
1832
1825
 
1833
- let load_start = offset;
1834
- let load_end = offset + size;
1835
- console.log(load_start, load_end);
1836
- console.log(
1837
- stub.data_start,
1838
- stub.data.length,
1839
- stub.text_start,
1840
- stub.text.length,
1826
+ const load_start = offset;
1827
+ const load_end = offset + size;
1828
+ this.logger.debug(
1829
+ `Load range: ${toHex(load_start, 8)}-${toHex(load_end, 8)}`,
1830
+ );
1831
+ this.logger.debug(
1832
+ `Stub data: ${toHex(stub.data_start, 8)}, len: ${stub.data.length}, text: ${toHex(stub.text_start, 8)}, len: ${stub.text.length}`,
1841
1833
  );
1842
- for (let [start, end] of [
1834
+ for (const [start, end] of [
1843
1835
  [stub.data_start, stub.data_start + stub.data.length],
1844
1836
  [stub.text_start, stub.text_start + stub.text.length],
1845
1837
  ]) {
@@ -1859,6 +1851,7 @@ class EspStubLoader extends ESPLoader {
1859
1851
  );
1860
1852
  }
1861
1853
  }
1854
+ return [0, []];
1862
1855
  }
1863
1856
 
1864
1857
  /**