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 +8 -0
- package/dist/const.js +10 -0
- package/dist/esp_loader.d.ts +12 -0
- package/dist/esp_loader.js +143 -3
- package/dist/web/index.js +1 -1
- package/js/modules/esptool.js +1 -1
- package/package.json +1 -1
- package/src/const.ts +12 -0
- package/src/esp_loader.ts +172 -2
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;
|
package/dist/esp_loader.d.ts
CHANGED
|
@@ -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.
|
package/dist/esp_loader.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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.
|