tasmota-webserial-esptool 9.2.3 → 9.2.5

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/dist/const.d.ts CHANGED
@@ -67,6 +67,10 @@ export declare const ESP32S2_SPI_MISO_DLEN_OFFS = 40;
67
67
  export declare const ESP32S2_SPI_W0_OFFS = 88;
68
68
  export declare const ESP32S2_UART_DATE_REG_ADDR = 1610612856;
69
69
  export declare const ESP32S2_BOOTLOADER_FLASH_OFFSET = 4096;
70
+ export declare const ESP32S2_RTC_CNTL_WDTWPROTECT_REG = 1061191852;
71
+ export declare const ESP32S2_RTC_CNTL_WDTCONFIG0_REG = 1061191828;
72
+ export declare const ESP32S2_RTC_CNTL_WDTCONFIG1_REG = 1061191832;
73
+ export declare const ESP32S2_RTC_CNTL_WDT_WKEY = 1356348065;
70
74
  export declare const ESP32S3_SPI_REG_BASE = 1610620928;
71
75
  export declare const ESP32S3_BASEFUSEADDR = 1610641408;
72
76
  export declare const ESP32S3_MACFUSEADDR: number;
@@ -78,6 +82,10 @@ export declare const ESP32S3_SPI_MISO_DLEN_OFFS = 40;
78
82
  export declare const ESP32S3_SPI_W0_OFFS = 88;
79
83
  export declare const ESP32S3_UART_DATE_REG_ADDR = 1610612864;
80
84
  export declare const ESP32S3_BOOTLOADER_FLASH_OFFSET = 0;
85
+ export declare const ESP32S3_RTC_CNTL_WDTWPROTECT_REG = 1610645680;
86
+ export declare const ESP32S3_RTC_CNTL_WDTCONFIG0_REG = 1610645656;
87
+ export declare const ESP32S3_RTC_CNTL_WDTCONFIG1_REG = 1610645660;
88
+ export declare const ESP32S3_RTC_CNTL_WDT_WKEY = 1356348065;
81
89
  export declare const ESP32C2_SPI_REG_BASE = 1610620928;
82
90
  export declare const ESP32C2_BASEFUSEADDR = 1610647552;
83
91
  export declare const ESP32C2_MACFUSEADDR: number;
package/dist/const.js CHANGED
@@ -86,6 +86,11 @@ export const ESP32S2_SPI_MISO_DLEN_OFFS = 0x28;
86
86
  export const ESP32S2_SPI_W0_OFFS = 0x58;
87
87
  export const ESP32S2_UART_DATE_REG_ADDR = 0x60000078;
88
88
  export const ESP32S2_BOOTLOADER_FLASH_OFFSET = 0x1000;
89
+ // ESP32-S2 RTC Watchdog Timer registers for USB-OTG reset
90
+ export const ESP32S2_RTC_CNTL_WDTWPROTECT_REG = 0x3f4080ac;
91
+ export const ESP32S2_RTC_CNTL_WDTCONFIG0_REG = 0x3f408094;
92
+ export const ESP32S2_RTC_CNTL_WDTCONFIG1_REG = 0x3f408098;
93
+ export const ESP32S2_RTC_CNTL_WDT_WKEY = 0x50d83aa1;
89
94
  export const ESP32S3_SPI_REG_BASE = 0x60002000;
90
95
  export const ESP32S3_BASEFUSEADDR = 0x60007000;
91
96
  export const ESP32S3_MACFUSEADDR = 0x60007000 + 0x044;
@@ -97,6 +102,11 @@ export const ESP32S3_SPI_MISO_DLEN_OFFS = 0x28;
97
102
  export const ESP32S3_SPI_W0_OFFS = 0x58;
98
103
  export const ESP32S3_UART_DATE_REG_ADDR = 0x60000080;
99
104
  export const ESP32S3_BOOTLOADER_FLASH_OFFSET = 0x0;
105
+ // ESP32-S3 RTC Watchdog Timer registers for USB-OTG reset
106
+ export const ESP32S3_RTC_CNTL_WDTWPROTECT_REG = 0x600080b0;
107
+ export const ESP32S3_RTC_CNTL_WDTCONFIG0_REG = 0x60008098;
108
+ export const ESP32S3_RTC_CNTL_WDTCONFIG1_REG = 0x6000809c;
109
+ export const ESP32S3_RTC_CNTL_WDT_WKEY = 0x50d83aa1;
100
110
  export const ESP32C2_SPI_REG_BASE = 0x60002000;
101
111
  export const ESP32C2_BASEFUSEADDR = 0x60008800;
102
112
  export const ESP32C2_MACFUSEADDR = 0x60008800 + 0x044;
@@ -172,6 +172,12 @@ export declare class ESPLoader extends EventTarget {
172
172
  * Similar to esptool.py's connect() method with multiple reset strategies
173
173
  */
174
174
  connectWithResetStrategies(): Promise<void>;
175
+ /**
176
+ * @name watchdogReset
177
+ * Watchdog reset for ESP32-S2/S3 with USB-OTG
178
+ * Uses RTC watchdog timer to reset the chip - works when DTR/RTS signals are not available
179
+ */
180
+ watchdogReset(): Promise<void>;
175
181
  hardReset(bootloader?: boolean): Promise<void>;
176
182
  /**
177
183
  * @name macAddr
@@ -321,6 +327,12 @@ export declare class ESPLoader extends EventTarget {
321
327
  * Reconnect the serial port to flush browser buffers and reload stub
322
328
  */
323
329
  reconnect(): Promise<void>;
330
+ /**
331
+ * @name reconnectToBootloader
332
+ * Close and reopen the port, then reset ESP to bootloader mode
333
+ * This is needed after Improv or other operations that leave ESP in firmware mode
334
+ */
335
+ reconnectToBootloader(): Promise<void>;
324
336
  /**
325
337
  * @name drainInputBuffer
326
338
  * Actively drain the input buffer by reading data for a specified time.
@@ -1,5 +1,5 @@
1
1
  /// <reference types="@types/w3c-web-serial" />
2
- import { CHIP_FAMILY_ESP32, CHIP_FAMILY_ESP32S2, CHIP_FAMILY_ESP32S3, CHIP_FAMILY_ESP32C2, CHIP_FAMILY_ESP32C3, CHIP_FAMILY_ESP32C5, CHIP_FAMILY_ESP32C6, CHIP_FAMILY_ESP32C61, CHIP_FAMILY_ESP32H2, CHIP_FAMILY_ESP32H4, CHIP_FAMILY_ESP32H21, CHIP_FAMILY_ESP32P4, CHIP_FAMILY_ESP32S31, CHIP_FAMILY_ESP8266, MAX_TIMEOUT, DEFAULT_TIMEOUT, ERASE_REGION_TIMEOUT_PER_MB, ESP_CHANGE_BAUDRATE, ESP_CHECKSUM_MAGIC, ESP_FLASH_BEGIN, ESP_FLASH_DATA, ESP_FLASH_END, ESP_MEM_BEGIN, ESP_MEM_DATA, ESP_MEM_END, ESP_READ_REG, ESP_WRITE_REG, ESP_SPI_ATTACH, ESP_SYNC, ESP_GET_SECURITY_INFO, FLASH_SECTOR_SIZE, FLASH_WRITE_SIZE, STUB_FLASH_WRITE_SIZE, MEM_END_ROM_TIMEOUT, ROM_INVALID_RECV_MSG, SYNC_PACKET, SYNC_TIMEOUT, USB_RAM_BLOCK, ESP_ERASE_FLASH, ESP_ERASE_REGION, ESP_READ_FLASH, CHIP_ERASE_TIMEOUT, FLASH_READ_TIMEOUT, timeoutPerMb, ESP_ROM_BAUD, USB_JTAG_SERIAL_PID, ESP_FLASH_DEFL_BEGIN, ESP_FLASH_DEFL_DATA, ESP_FLASH_DEFL_END, getSpiFlashAddresses, DETECTED_FLASH_SIZES, CHIP_DETECT_MAGIC_REG_ADDR, CHIP_DETECT_MAGIC_VALUES, CHIP_ID_TO_INFO, ESP32P4_EFUSE_BLOCK1_ADDR, SlipReadError, } from "./const";
2
+ import { CHIP_FAMILY_ESP32, CHIP_FAMILY_ESP32S2, CHIP_FAMILY_ESP32S3, CHIP_FAMILY_ESP32C2, CHIP_FAMILY_ESP32C3, CHIP_FAMILY_ESP32C5, CHIP_FAMILY_ESP32C6, CHIP_FAMILY_ESP32C61, CHIP_FAMILY_ESP32H2, CHIP_FAMILY_ESP32H4, CHIP_FAMILY_ESP32H21, CHIP_FAMILY_ESP32P4, CHIP_FAMILY_ESP32S31, CHIP_FAMILY_ESP8266, MAX_TIMEOUT, DEFAULT_TIMEOUT, ERASE_REGION_TIMEOUT_PER_MB, ESP_CHANGE_BAUDRATE, ESP_CHECKSUM_MAGIC, ESP_FLASH_BEGIN, ESP_FLASH_DATA, ESP_FLASH_END, ESP_MEM_BEGIN, ESP_MEM_DATA, ESP_MEM_END, ESP_READ_REG, ESP_WRITE_REG, ESP_SPI_ATTACH, ESP_SYNC, ESP_GET_SECURITY_INFO, FLASH_SECTOR_SIZE, FLASH_WRITE_SIZE, STUB_FLASH_WRITE_SIZE, MEM_END_ROM_TIMEOUT, ROM_INVALID_RECV_MSG, SYNC_PACKET, SYNC_TIMEOUT, USB_RAM_BLOCK, ESP_ERASE_FLASH, ESP_ERASE_REGION, ESP_READ_FLASH, CHIP_ERASE_TIMEOUT, FLASH_READ_TIMEOUT, timeoutPerMb, ESP_ROM_BAUD, USB_JTAG_SERIAL_PID, ESP_FLASH_DEFL_BEGIN, ESP_FLASH_DEFL_DATA, ESP_FLASH_DEFL_END, getSpiFlashAddresses, DETECTED_FLASH_SIZES, CHIP_DETECT_MAGIC_REG_ADDR, CHIP_DETECT_MAGIC_VALUES, CHIP_ID_TO_INFO, ESP32P4_EFUSE_BLOCK1_ADDR, SlipReadError, ESP32S2_RTC_CNTL_WDTWPROTECT_REG, ESP32S2_RTC_CNTL_WDTCONFIG0_REG, ESP32S2_RTC_CNTL_WDTCONFIG1_REG, ESP32S2_RTC_CNTL_WDT_WKEY, ESP32S3_RTC_CNTL_WDTWPROTECT_REG, ESP32S3_RTC_CNTL_WDTCONFIG0_REG, ESP32S3_RTC_CNTL_WDTCONFIG1_REG, ESP32S3_RTC_CNTL_WDT_WKEY, } from "./const";
3
3
  import { getStubCode } from "./stubs";
4
4
  import { hexFormatter, sleep, slipEncode, toHex } from "./util";
5
5
  import { deflate } from "pako";
@@ -1075,6 +1075,45 @@ export class ESPLoader extends EventTarget {
1075
1075
  this._abandonCurrentOperation = false;
1076
1076
  throw new Error(`Couldn't sync to ESP. Try resetting manually. Last error: ${lastError === null || lastError === void 0 ? void 0 : lastError.message}`);
1077
1077
  }
1078
+ /**
1079
+ * @name watchdogReset
1080
+ * Watchdog reset for ESP32-S2/S3 with USB-OTG
1081
+ * Uses RTC watchdog timer to reset the chip - works when DTR/RTS signals are not available
1082
+ */
1083
+ async watchdogReset() {
1084
+ this.logger.log("Hard resetting with watchdog timer...");
1085
+ // Select correct register addresses based on chip family
1086
+ let WDTWPROTECT_REG;
1087
+ let WDTCONFIG0_REG;
1088
+ let WDTCONFIG1_REG;
1089
+ let WDT_WKEY;
1090
+ if (this.chipFamily === CHIP_FAMILY_ESP32S2) {
1091
+ WDTWPROTECT_REG = ESP32S2_RTC_CNTL_WDTWPROTECT_REG;
1092
+ WDTCONFIG0_REG = ESP32S2_RTC_CNTL_WDTCONFIG0_REG;
1093
+ WDTCONFIG1_REG = ESP32S2_RTC_CNTL_WDTCONFIG1_REG;
1094
+ WDT_WKEY = ESP32S2_RTC_CNTL_WDT_WKEY;
1095
+ }
1096
+ else if (this.chipFamily === CHIP_FAMILY_ESP32S3) {
1097
+ WDTWPROTECT_REG = ESP32S3_RTC_CNTL_WDTWPROTECT_REG;
1098
+ WDTCONFIG0_REG = ESP32S3_RTC_CNTL_WDTCONFIG0_REG;
1099
+ WDTCONFIG1_REG = ESP32S3_RTC_CNTL_WDTCONFIG1_REG;
1100
+ WDT_WKEY = ESP32S3_RTC_CNTL_WDT_WKEY;
1101
+ }
1102
+ else {
1103
+ throw new Error(`watchdogReset() is only supported for ESP32-S2 and ESP32-S3, not ${this.chipFamily}`);
1104
+ }
1105
+ // Unlock watchdog registers
1106
+ await this.writeRegister(WDTWPROTECT_REG, WDT_WKEY, undefined, 0);
1107
+ // Set WDT timeout to 2000ms
1108
+ await this.writeRegister(WDTCONFIG1_REG, 2000, undefined, 0);
1109
+ // Enable WDT: bit 31 = enable, bits 28-30 = stage, bit 8 = sys reset, bits 0-2 = prescaler
1110
+ const wdtConfig = (1 << 31) | (5 << 28) | (1 << 8) | 2;
1111
+ await this.writeRegister(WDTCONFIG0_REG, wdtConfig, undefined, 0);
1112
+ // Lock watchdog registers
1113
+ await this.writeRegister(WDTWPROTECT_REG, 0, undefined, 0);
1114
+ // Wait for reset to take effect
1115
+ await this.sleep(500);
1116
+ }
1078
1117
  async hardReset(bootloader = false) {
1079
1118
  if (bootloader) {
1080
1119
  // enter flash mode
@@ -1096,7 +1135,14 @@ export class ESPLoader extends EventTarget {
1096
1135
  }
1097
1136
  else {
1098
1137
  // just reset (no bootloader mode)
1099
- if (this.isWebUSB()) {
1138
+ // For ESP32-S2/S3 with USB-OTG, use watchdog reset instead of DTR/RTS
1139
+ if (this.port.getInfo().usbProductId === USB_JTAG_SERIAL_PID &&
1140
+ (this.chipFamily === CHIP_FAMILY_ESP32S2 ||
1141
+ this.chipFamily === CHIP_FAMILY_ESP32S3)) {
1142
+ await this.watchdogReset();
1143
+ this.logger.log("Watchdog reset (USB-OTG).");
1144
+ }
1145
+ else if (this.isWebUSB()) {
1100
1146
  // WebUSB: Use longer delays for better compatibility
1101
1147
  await this.setRTSWebUSB(true); // EN->LOW
1102
1148
  await this.sleep(200);
@@ -2128,7 +2174,9 @@ export class ESPLoader extends EventTarget {
2128
2174
  }
2129
2175
  }
2130
2176
  get _currentBaudRate() {
2131
- return this._parent ? this._parent._currentBaudRate : this.__currentBaudRate;
2177
+ return this._parent
2178
+ ? this._parent._currentBaudRate
2179
+ : this.__currentBaudRate;
2132
2180
  }
2133
2181
  set _currentBaudRate(value) {
2134
2182
  if (this._parent) {
@@ -2393,6 +2441,98 @@ export class ESPLoader extends EventTarget {
2393
2441
  throw err;
2394
2442
  }
2395
2443
  }
2444
+ /**
2445
+ * @name reconnectToBootloader
2446
+ * Close and reopen the port, then reset ESP to bootloader mode
2447
+ * This is needed after Improv or other operations that leave ESP in firmware mode
2448
+ */
2449
+ async reconnectToBootloader() {
2450
+ if (this._parent) {
2451
+ await this._parent.reconnectToBootloader();
2452
+ return;
2453
+ }
2454
+ try {
2455
+ this.logger.log("Reconnecting to bootloader mode...");
2456
+ this.connected = false;
2457
+ this.__inputBuffer = [];
2458
+ this.__inputBufferReadIndex = 0;
2459
+ // Wait for pending writes to complete
2460
+ try {
2461
+ await this._writeChain;
2462
+ }
2463
+ catch (err) {
2464
+ this.logger.debug(`Pending write error during reconnect: ${err}`);
2465
+ }
2466
+ // Block new writes during port close/open
2467
+ this._isReconfiguring = true;
2468
+ // Release persistent writer
2469
+ if (this._writer) {
2470
+ try {
2471
+ this._writer.releaseLock();
2472
+ }
2473
+ catch (err) {
2474
+ this.logger.debug(`Writer release error during reconnect: ${err}`);
2475
+ }
2476
+ this._writer = undefined;
2477
+ }
2478
+ // Cancel reader
2479
+ if (this._reader) {
2480
+ try {
2481
+ await this._reader.cancel();
2482
+ }
2483
+ catch (err) {
2484
+ this.logger.debug(`Reader cancel error: ${err}`);
2485
+ }
2486
+ this._reader = undefined;
2487
+ }
2488
+ // Close port
2489
+ try {
2490
+ await this.port.close();
2491
+ this.logger.log("Port closed");
2492
+ }
2493
+ catch (err) {
2494
+ this.logger.debug(`Port close error: ${err}`);
2495
+ }
2496
+ // Open the port
2497
+ this.logger.debug("Opening port...");
2498
+ try {
2499
+ await this.port.open({ baudRate: ESP_ROM_BAUD });
2500
+ this.connected = true;
2501
+ }
2502
+ catch (err) {
2503
+ throw new Error(`Failed to open port: ${err}`);
2504
+ }
2505
+ // Verify port streams are available
2506
+ if (!this.port.readable || !this.port.writable) {
2507
+ throw new Error(`Port streams not available after open (readable: ${!!this.port.readable}, writable: ${!!this.port.writable})`);
2508
+ }
2509
+ // Port is now open and ready - allow writes for initialization
2510
+ this._isReconfiguring = false;
2511
+ // Reset chip info and stub state
2512
+ this.__chipFamily = undefined;
2513
+ this.chipName = "Unknown Chip";
2514
+ this.IS_STUB = false;
2515
+ // Start read loop
2516
+ if (!this._parent) {
2517
+ this.__inputBuffer = [];
2518
+ this.__inputBufferReadIndex = 0;
2519
+ this.__totalBytesRead = 0;
2520
+ this.readLoop();
2521
+ }
2522
+ // Wait for readLoop to start
2523
+ await sleep(100);
2524
+ // Reset to bootloader mode using multiple strategies
2525
+ await this.connectWithResetStrategies();
2526
+ // Detect chip type
2527
+ await this.detectChip();
2528
+ this.logger.log(`Reconnected to bootloader: ${this.chipName}`);
2529
+ }
2530
+ catch (err) {
2531
+ // Ensure flag is reset on error
2532
+ this._isReconfiguring = false;
2533
+ throw err;
2534
+ }
2535
+ }
2396
2536
  /**
2397
2537
  * @name drainInputBuffer
2398
2538
  * Actively drain the input buffer by reading data for a specified time.