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/src/esp_loader.ts
CHANGED
|
@@ -60,6 +60,14 @@ import {
|
|
|
60
60
|
CHIP_ID_TO_INFO,
|
|
61
61
|
ESP32P4_EFUSE_BLOCK1_ADDR,
|
|
62
62
|
SlipReadError,
|
|
63
|
+
ESP32S2_RTC_CNTL_WDTWPROTECT_REG,
|
|
64
|
+
ESP32S2_RTC_CNTL_WDTCONFIG0_REG,
|
|
65
|
+
ESP32S2_RTC_CNTL_WDTCONFIG1_REG,
|
|
66
|
+
ESP32S2_RTC_CNTL_WDT_WKEY,
|
|
67
|
+
ESP32S3_RTC_CNTL_WDTWPROTECT_REG,
|
|
68
|
+
ESP32S3_RTC_CNTL_WDTCONFIG0_REG,
|
|
69
|
+
ESP32S3_RTC_CNTL_WDTCONFIG1_REG,
|
|
70
|
+
ESP32S3_RTC_CNTL_WDT_WKEY,
|
|
63
71
|
} from "./const";
|
|
64
72
|
import { getStubCode } from "./stubs";
|
|
65
73
|
import { hexFormatter, sleep, slipEncode, toHex } from "./util";
|
|
@@ -1349,6 +1357,53 @@ export class ESPLoader extends EventTarget {
|
|
|
1349
1357
|
);
|
|
1350
1358
|
}
|
|
1351
1359
|
|
|
1360
|
+
/**
|
|
1361
|
+
* @name watchdogReset
|
|
1362
|
+
* Watchdog reset for ESP32-S2/S3 with USB-OTG
|
|
1363
|
+
* Uses RTC watchdog timer to reset the chip - works when DTR/RTS signals are not available
|
|
1364
|
+
*/
|
|
1365
|
+
async watchdogReset() {
|
|
1366
|
+
this.logger.log("Hard resetting with watchdog timer...");
|
|
1367
|
+
|
|
1368
|
+
// Select correct register addresses based on chip family
|
|
1369
|
+
let WDTWPROTECT_REG: number;
|
|
1370
|
+
let WDTCONFIG0_REG: number;
|
|
1371
|
+
let WDTCONFIG1_REG: number;
|
|
1372
|
+
let WDT_WKEY: number;
|
|
1373
|
+
|
|
1374
|
+
if (this.chipFamily === CHIP_FAMILY_ESP32S2) {
|
|
1375
|
+
WDTWPROTECT_REG = ESP32S2_RTC_CNTL_WDTWPROTECT_REG;
|
|
1376
|
+
WDTCONFIG0_REG = ESP32S2_RTC_CNTL_WDTCONFIG0_REG;
|
|
1377
|
+
WDTCONFIG1_REG = ESP32S2_RTC_CNTL_WDTCONFIG1_REG;
|
|
1378
|
+
WDT_WKEY = ESP32S2_RTC_CNTL_WDT_WKEY;
|
|
1379
|
+
} else if (this.chipFamily === CHIP_FAMILY_ESP32S3) {
|
|
1380
|
+
WDTWPROTECT_REG = ESP32S3_RTC_CNTL_WDTWPROTECT_REG;
|
|
1381
|
+
WDTCONFIG0_REG = ESP32S3_RTC_CNTL_WDTCONFIG0_REG;
|
|
1382
|
+
WDTCONFIG1_REG = ESP32S3_RTC_CNTL_WDTCONFIG1_REG;
|
|
1383
|
+
WDT_WKEY = ESP32S3_RTC_CNTL_WDT_WKEY;
|
|
1384
|
+
} else {
|
|
1385
|
+
throw new Error(
|
|
1386
|
+
`watchdogReset() is only supported for ESP32-S2 and ESP32-S3, not ${this.chipFamily}`,
|
|
1387
|
+
);
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
// Unlock watchdog registers
|
|
1391
|
+
await this.writeRegister(WDTWPROTECT_REG, WDT_WKEY, undefined, 0);
|
|
1392
|
+
|
|
1393
|
+
// Set WDT timeout to 2000ms
|
|
1394
|
+
await this.writeRegister(WDTCONFIG1_REG, 2000, undefined, 0);
|
|
1395
|
+
|
|
1396
|
+
// Enable WDT: bit 31 = enable, bits 28-30 = stage, bit 8 = sys reset, bits 0-2 = prescaler
|
|
1397
|
+
const wdtConfig = (1 << 31) | (5 << 28) | (1 << 8) | 2;
|
|
1398
|
+
await this.writeRegister(WDTCONFIG0_REG, wdtConfig, undefined, 0);
|
|
1399
|
+
|
|
1400
|
+
// Lock watchdog registers
|
|
1401
|
+
await this.writeRegister(WDTWPROTECT_REG, 0, undefined, 0);
|
|
1402
|
+
|
|
1403
|
+
// Wait for reset to take effect
|
|
1404
|
+
await this.sleep(500);
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1352
1407
|
async hardReset(bootloader = false) {
|
|
1353
1408
|
if (bootloader) {
|
|
1354
1409
|
// enter flash mode
|
|
@@ -1367,7 +1422,15 @@ export class ESPLoader extends EventTarget {
|
|
|
1367
1422
|
}
|
|
1368
1423
|
} else {
|
|
1369
1424
|
// just reset (no bootloader mode)
|
|
1370
|
-
|
|
1425
|
+
// For ESP32-S2/S3 with USB-OTG, use watchdog reset instead of DTR/RTS
|
|
1426
|
+
if (
|
|
1427
|
+
this.port.getInfo().usbProductId === USB_JTAG_SERIAL_PID &&
|
|
1428
|
+
(this.chipFamily === CHIP_FAMILY_ESP32S2 ||
|
|
1429
|
+
this.chipFamily === CHIP_FAMILY_ESP32S3)
|
|
1430
|
+
) {
|
|
1431
|
+
await this.watchdogReset();
|
|
1432
|
+
this.logger.log("Watchdog reset (USB-OTG).");
|
|
1433
|
+
} else if (this.isWebUSB()) {
|
|
1371
1434
|
// WebUSB: Use longer delays for better compatibility
|
|
1372
1435
|
await this.setRTSWebUSB(true); // EN->LOW
|
|
1373
1436
|
await this.sleep(200);
|
|
@@ -2634,7 +2697,9 @@ export class ESPLoader extends EventTarget {
|
|
|
2634
2697
|
}
|
|
2635
2698
|
|
|
2636
2699
|
private get _currentBaudRate(): number {
|
|
2637
|
-
return this._parent
|
|
2700
|
+
return this._parent
|
|
2701
|
+
? this._parent._currentBaudRate
|
|
2702
|
+
: this.__currentBaudRate;
|
|
2638
2703
|
}
|
|
2639
2704
|
|
|
2640
2705
|
private set _currentBaudRate(value: number) {
|
|
@@ -2939,6 +3004,111 @@ export class ESPLoader extends EventTarget {
|
|
|
2939
3004
|
}
|
|
2940
3005
|
}
|
|
2941
3006
|
|
|
3007
|
+
/**
|
|
3008
|
+
* @name reconnectToBootloader
|
|
3009
|
+
* Close and reopen the port, then reset ESP to bootloader mode
|
|
3010
|
+
* This is needed after Improv or other operations that leave ESP in firmware mode
|
|
3011
|
+
*/
|
|
3012
|
+
async reconnectToBootloader(): Promise<void> {
|
|
3013
|
+
if (this._parent) {
|
|
3014
|
+
await this._parent.reconnectToBootloader();
|
|
3015
|
+
return;
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
try {
|
|
3019
|
+
this.logger.log("Reconnecting to bootloader mode...");
|
|
3020
|
+
|
|
3021
|
+
this.connected = false;
|
|
3022
|
+
this.__inputBuffer = [];
|
|
3023
|
+
this.__inputBufferReadIndex = 0;
|
|
3024
|
+
|
|
3025
|
+
// Wait for pending writes to complete
|
|
3026
|
+
try {
|
|
3027
|
+
await this._writeChain;
|
|
3028
|
+
} catch (err) {
|
|
3029
|
+
this.logger.debug(`Pending write error during reconnect: ${err}`);
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
// Block new writes during port close/open
|
|
3033
|
+
this._isReconfiguring = true;
|
|
3034
|
+
|
|
3035
|
+
// Release persistent writer
|
|
3036
|
+
if (this._writer) {
|
|
3037
|
+
try {
|
|
3038
|
+
this._writer.releaseLock();
|
|
3039
|
+
} catch (err) {
|
|
3040
|
+
this.logger.debug(`Writer release error during reconnect: ${err}`);
|
|
3041
|
+
}
|
|
3042
|
+
this._writer = undefined;
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
// Cancel reader
|
|
3046
|
+
if (this._reader) {
|
|
3047
|
+
try {
|
|
3048
|
+
await this._reader.cancel();
|
|
3049
|
+
} catch (err) {
|
|
3050
|
+
this.logger.debug(`Reader cancel error: ${err}`);
|
|
3051
|
+
}
|
|
3052
|
+
this._reader = undefined;
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3055
|
+
// Close port
|
|
3056
|
+
try {
|
|
3057
|
+
await this.port.close();
|
|
3058
|
+
this.logger.log("Port closed");
|
|
3059
|
+
} catch (err) {
|
|
3060
|
+
this.logger.debug(`Port close error: ${err}`);
|
|
3061
|
+
}
|
|
3062
|
+
|
|
3063
|
+
// Open the port
|
|
3064
|
+
this.logger.debug("Opening port...");
|
|
3065
|
+
try {
|
|
3066
|
+
await this.port.open({ baudRate: ESP_ROM_BAUD });
|
|
3067
|
+
this.connected = true;
|
|
3068
|
+
} catch (err) {
|
|
3069
|
+
throw new Error(`Failed to open port: ${err}`);
|
|
3070
|
+
}
|
|
3071
|
+
|
|
3072
|
+
// Verify port streams are available
|
|
3073
|
+
if (!this.port.readable || !this.port.writable) {
|
|
3074
|
+
throw new Error(
|
|
3075
|
+
`Port streams not available after open (readable: ${!!this.port.readable}, writable: ${!!this.port.writable})`,
|
|
3076
|
+
);
|
|
3077
|
+
}
|
|
3078
|
+
|
|
3079
|
+
// Port is now open and ready - allow writes for initialization
|
|
3080
|
+
this._isReconfiguring = false;
|
|
3081
|
+
|
|
3082
|
+
// Reset chip info and stub state
|
|
3083
|
+
this.__chipFamily = undefined;
|
|
3084
|
+
this.chipName = "Unknown Chip";
|
|
3085
|
+
this.IS_STUB = false;
|
|
3086
|
+
|
|
3087
|
+
// Start read loop
|
|
3088
|
+
if (!this._parent) {
|
|
3089
|
+
this.__inputBuffer = [];
|
|
3090
|
+
this.__inputBufferReadIndex = 0;
|
|
3091
|
+
this.__totalBytesRead = 0;
|
|
3092
|
+
this.readLoop();
|
|
3093
|
+
}
|
|
3094
|
+
|
|
3095
|
+
// Wait for readLoop to start
|
|
3096
|
+
await sleep(100);
|
|
3097
|
+
|
|
3098
|
+
// Reset to bootloader mode using multiple strategies
|
|
3099
|
+
await this.connectWithResetStrategies();
|
|
3100
|
+
|
|
3101
|
+
// Detect chip type
|
|
3102
|
+
await this.detectChip();
|
|
3103
|
+
|
|
3104
|
+
this.logger.log(`Reconnected to bootloader: ${this.chipName}`);
|
|
3105
|
+
} catch (err) {
|
|
3106
|
+
// Ensure flag is reset on error
|
|
3107
|
+
this._isReconfiguring = false;
|
|
3108
|
+
throw err;
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
|
|
2942
3112
|
/**
|
|
2943
3113
|
* @name drainInputBuffer
|
|
2944
3114
|
* Actively drain the input buffer by reading data for a specified time.
|