tasmota-webserial-esptool 9.2.20 → 9.2.21
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 +3 -3
- package/dist/esp_loader.d.ts +5 -3
- package/dist/esp_loader.js +69 -70
- package/dist/web/index.js +1 -1
- package/js/modules/esptool.js +1 -1
- package/package.json +15 -10
- package/src/const.ts +3 -3
- package/src/esp_loader.ts +80 -83
package/src/esp_loader.ts
CHANGED
|
@@ -84,14 +84,6 @@ import {
|
|
|
84
84
|
ESP32S3_RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK,
|
|
85
85
|
ESP32C3_EFUSE_RD_MAC_SPI_SYS_3_REG,
|
|
86
86
|
ESP32C3_EFUSE_RD_MAC_SPI_SYS_5_REG,
|
|
87
|
-
ESP32C3_RTC_CNTL_WDTWPROTECT_REG,
|
|
88
|
-
ESP32C3_RTC_CNTL_WDTCONFIG0_REG,
|
|
89
|
-
ESP32C3_RTC_CNTL_WDTCONFIG1_REG,
|
|
90
|
-
ESP32C3_RTC_CNTL_WDT_WKEY,
|
|
91
|
-
ESP32C5_C6_RTC_CNTL_WDTWPROTECT_REG,
|
|
92
|
-
ESP32C5_C6_RTC_CNTL_WDTCONFIG0_REG,
|
|
93
|
-
ESP32C5_C6_RTC_CNTL_WDTCONFIG1_REG,
|
|
94
|
-
ESP32C5_C6_RTC_CNTL_WDT_WKEY,
|
|
95
87
|
ESP32C5_UART_CLKDIV_REG,
|
|
96
88
|
ESP32C5_PCR_SYSCLK_CONF_REG,
|
|
97
89
|
ESP32C5_PCR_SYSCLK_XTAL_FREQ_V,
|
|
@@ -1015,7 +1007,8 @@ export class ESPLoader extends EventTarget {
|
|
|
1015
1007
|
private async runSignalSequence(
|
|
1016
1008
|
steps: Array<{ dtr?: boolean; rts?: boolean; delayMs?: number }>,
|
|
1017
1009
|
): Promise<void> {
|
|
1018
|
-
const webusb =
|
|
1010
|
+
const webusb =
|
|
1011
|
+
(this.port as unknown as { isWebUSB?: boolean }).isWebUSB === true;
|
|
1019
1012
|
for (const step of steps) {
|
|
1020
1013
|
if (step.dtr !== undefined && step.rts !== undefined) {
|
|
1021
1014
|
if (webusb) {
|
|
@@ -1549,7 +1542,7 @@ export class ESPLoader extends EventTarget {
|
|
|
1549
1542
|
`Connected CDC/JTAG successfully with ${strategy.name} reset.`,
|
|
1550
1543
|
);
|
|
1551
1544
|
return;
|
|
1552
|
-
} catch
|
|
1545
|
+
} catch {
|
|
1553
1546
|
throw new Error("Sync timeout or abandoned");
|
|
1554
1547
|
}
|
|
1555
1548
|
}
|
|
@@ -1588,18 +1581,20 @@ export class ESPLoader extends EventTarget {
|
|
|
1588
1581
|
|
|
1589
1582
|
/**
|
|
1590
1583
|
* @name watchdogReset
|
|
1591
|
-
* Watchdog reset for ESP32-S2/S3/
|
|
1584
|
+
* Watchdog reset for ESP32-S2/S3/P4 with USB-OTG or USB-JTAG/Serial
|
|
1592
1585
|
* Uses RTC watchdog timer to reset the chip - works when DTR/RTS signals are not available
|
|
1593
1586
|
* This is an alias for rtcWdtResetChipSpecific() for backwards compatibility
|
|
1587
|
+
* Note: ESP32-C3, ESP32-C5, ESP32-C6 do NOT boot correctly after WDT reset
|
|
1594
1588
|
*/
|
|
1595
1589
|
async watchdogReset() {
|
|
1596
1590
|
await this.rtcWdtResetChipSpecific();
|
|
1597
1591
|
}
|
|
1598
1592
|
|
|
1599
1593
|
/**
|
|
1600
|
-
* RTC watchdog timer reset for ESP32-S2, ESP32-S3,
|
|
1594
|
+
* RTC watchdog timer reset for ESP32-S2, ESP32-S3, and ESP32-P4
|
|
1601
1595
|
* Uses specific registers for each chip family
|
|
1602
|
-
* Note: ESP32-
|
|
1596
|
+
* Note: ESP32-C3 does NOT boot correctly after WDT reset
|
|
1597
|
+
* Note: ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2 do NOT support WDT reset (no usable RTC WDT path)
|
|
1603
1598
|
*/
|
|
1604
1599
|
public async rtcWdtResetChipSpecific(): Promise<void> {
|
|
1605
1600
|
this.logger.debug("Hard resetting with watchdog timer...");
|
|
@@ -1619,20 +1614,6 @@ export class ESPLoader extends EventTarget {
|
|
|
1619
1614
|
WDTCONFIG0_REG = ESP32S3_RTC_CNTL_WDTCONFIG0_REG;
|
|
1620
1615
|
WDTCONFIG1_REG = ESP32S3_RTC_CNTL_WDTCONFIG1_REG;
|
|
1621
1616
|
WDT_WKEY = ESP32S3_RTC_CNTL_WDT_WKEY;
|
|
1622
|
-
} else if (this.chipFamily === CHIP_FAMILY_ESP32C3) {
|
|
1623
|
-
WDTWPROTECT_REG = ESP32C3_RTC_CNTL_WDTWPROTECT_REG;
|
|
1624
|
-
WDTCONFIG0_REG = ESP32C3_RTC_CNTL_WDTCONFIG0_REG;
|
|
1625
|
-
WDTCONFIG1_REG = ESP32C3_RTC_CNTL_WDTCONFIG1_REG;
|
|
1626
|
-
WDT_WKEY = ESP32C3_RTC_CNTL_WDT_WKEY;
|
|
1627
|
-
} else if (
|
|
1628
|
-
this.chipFamily === CHIP_FAMILY_ESP32C5 ||
|
|
1629
|
-
this.chipFamily === CHIP_FAMILY_ESP32C6
|
|
1630
|
-
) {
|
|
1631
|
-
// C5 and C6 use LP_WDT (Low Power Watchdog Timer)
|
|
1632
|
-
WDTWPROTECT_REG = ESP32C5_C6_RTC_CNTL_WDTWPROTECT_REG;
|
|
1633
|
-
WDTCONFIG0_REG = ESP32C5_C6_RTC_CNTL_WDTCONFIG0_REG;
|
|
1634
|
-
WDTCONFIG1_REG = ESP32C5_C6_RTC_CNTL_WDTCONFIG1_REG;
|
|
1635
|
-
WDT_WKEY = ESP32C5_C6_RTC_CNTL_WDT_WKEY;
|
|
1636
1617
|
} else if (this.chipFamily === CHIP_FAMILY_ESP32P4) {
|
|
1637
1618
|
// P4 uses LP_WDT (Low Power Watchdog Timer)
|
|
1638
1619
|
WDTWPROTECT_REG = ESP32P4_RTC_CNTL_WDTWPROTECT_REG;
|
|
@@ -1697,7 +1678,6 @@ export class ESPLoader extends EventTarget {
|
|
|
1697
1678
|
usbMode = { mode: "usb-jtag-serial", uartNo: 0 };
|
|
1698
1679
|
}
|
|
1699
1680
|
|
|
1700
|
-
// Check if chip supports WDT reset
|
|
1701
1681
|
// WDT reset is not needed for ESP32-C3
|
|
1702
1682
|
// WDT reset is supported by: ESP32-S2, ESP32-S3, ESP32-P4
|
|
1703
1683
|
// WDT reset is NOT supported by: ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2
|
|
@@ -1841,60 +1821,75 @@ export class ESPLoader extends EventTarget {
|
|
|
1841
1821
|
const isUsbJtagOrOtg = await this.detectUsbConnectionType();
|
|
1842
1822
|
|
|
1843
1823
|
if (isUsbJtagOrOtg) {
|
|
1844
|
-
// USB-JTAG/OTG devices:
|
|
1845
|
-
|
|
1824
|
+
// USB-JTAG/OTG devices: Check if chip supports WDT reset
|
|
1825
|
+
// Only S2, S3, P4 support WDT reset correctly
|
|
1826
|
+
// C3, C5, C6, C61, H2 do NOT boot correctly after WDT reset
|
|
1827
|
+
const supportsWdtReset =
|
|
1828
|
+
this.chipFamily === CHIP_FAMILY_ESP32S2 ||
|
|
1829
|
+
this.chipFamily === CHIP_FAMILY_ESP32S3 ||
|
|
1830
|
+
this.chipFamily === CHIP_FAMILY_ESP32P4;
|
|
1846
1831
|
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
mode: "uart" | "usb-jtag-serial" | "usb-otg";
|
|
1850
|
-
uartNo: number;
|
|
1851
|
-
};
|
|
1852
|
-
try {
|
|
1853
|
-
usbMode = await this.getUsbMode();
|
|
1854
|
-
this.logger.debug(
|
|
1855
|
-
`USB mode: ${usbMode.mode} (uartNo=${usbMode.uartNo})`,
|
|
1856
|
-
);
|
|
1857
|
-
} catch (err) {
|
|
1858
|
-
this.logger.debug(`Could not get USB mode: ${err}`);
|
|
1859
|
-
usbMode = { mode: "usb-jtag-serial", uartNo: 0 };
|
|
1860
|
-
}
|
|
1832
|
+
if (supportsWdtReset) {
|
|
1833
|
+
this.logger.debug("USB-JTAG/OTG detected - using WDT reset");
|
|
1861
1834
|
|
|
1862
|
-
|
|
1863
|
-
|
|
1835
|
+
// Get USB mode details
|
|
1836
|
+
let usbMode: {
|
|
1837
|
+
mode: "uart" | "usb-jtag-serial" | "usb-otg";
|
|
1838
|
+
uartNo: number;
|
|
1839
|
+
};
|
|
1864
1840
|
try {
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1841
|
+
usbMode = await this.getUsbMode();
|
|
1842
|
+
this.logger.debug(
|
|
1843
|
+
`USB mode: ${usbMode.mode} (uartNo=${usbMode.uartNo})`,
|
|
1844
|
+
);
|
|
1869
1845
|
} catch (err) {
|
|
1870
|
-
this.logger.debug(`Could not
|
|
1846
|
+
this.logger.debug(`Could not get USB mode: ${err}`);
|
|
1847
|
+
usbMode = { mode: "usb-jtag-serial", uartNo: 0 };
|
|
1871
1848
|
}
|
|
1872
|
-
}
|
|
1873
1849
|
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1850
|
+
// Clear force download flag for USB-OTG devices
|
|
1851
|
+
if (usbMode.mode === "usb-otg") {
|
|
1852
|
+
try {
|
|
1853
|
+
const flagCleared = await this._clearForceDownloadBootIfNeeded();
|
|
1854
|
+
if (flagCleared) {
|
|
1855
|
+
this.logger.debug("Force download boot flag cleared");
|
|
1856
|
+
}
|
|
1857
|
+
} catch (err) {
|
|
1858
|
+
this.logger.debug(`Could not clear force download flag: ${err}`);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
// Perform WDT reset
|
|
1863
|
+
await this.rtcWdtResetChipSpecific();
|
|
1864
|
+
this.logger.debug(`${this.chipName}: WDT reset to firmware complete`);
|
|
1865
|
+
return;
|
|
1866
|
+
} else {
|
|
1867
|
+
// C3, C5, C6, etc. - use classic reset (like external serial chips)
|
|
1868
|
+
this.logger.debug(
|
|
1869
|
+
`${this.chipName} does not support WDT reset - using classic reset instead`,
|
|
1870
|
+
);
|
|
1871
|
+
}
|
|
1878
1872
|
} else {
|
|
1879
1873
|
// External serial chip: Use classic reset
|
|
1880
1874
|
this.logger.debug(
|
|
1881
1875
|
"External serial chip detected - using classic reset",
|
|
1882
1876
|
);
|
|
1877
|
+
}
|
|
1883
1878
|
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1879
|
+
// Classic reset: used for external serial chips and USB-JTAG chips that do not support WDT reset
|
|
1880
|
+
if (this.isWebUSB()) {
|
|
1881
|
+
// WebUSB: Use longer delays for better compatibility
|
|
1882
|
+
await this.setRTSWebUSB(true); // EN->LOW
|
|
1883
|
+
await sleep(200);
|
|
1884
|
+
await this.setRTSWebUSB(false);
|
|
1885
|
+
await sleep(200);
|
|
1886
|
+
this.logger.debug("Hard reset to firmware (WebUSB).");
|
|
1887
|
+
} else {
|
|
1888
|
+
// Web Serial: Standard reset
|
|
1889
|
+
await this.setRTS(true); // EN->LOW
|
|
1890
|
+
await sleep(100);
|
|
1891
|
+
await this.setRTS(false);
|
|
1892
|
+
this.logger.debug("Hard reset to firmware.");
|
|
1898
1893
|
}
|
|
1899
1894
|
}
|
|
1900
1895
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
@@ -2483,9 +2478,9 @@ export class ESPLoader extends EventTarget {
|
|
|
2483
2478
|
|
|
2484
2479
|
// Restart Readloop
|
|
2485
2480
|
this.readLoop();
|
|
2486
|
-
} catch
|
|
2487
|
-
// this.logger.error(`Reconfigure port error
|
|
2488
|
-
// throw new Error(`Unable to change the baud rate to ${baud}
|
|
2481
|
+
} catch {
|
|
2482
|
+
// this.logger.error(`Reconfigure port error`);
|
|
2483
|
+
// throw new Error(`Unable to change the baud rate to ${baud}`);
|
|
2489
2484
|
} finally {
|
|
2490
2485
|
// Always reset flag, even on error or early return
|
|
2491
2486
|
this._isReconfiguring = false;
|
|
@@ -3276,8 +3271,8 @@ export class ESPLoader extends EventTarget {
|
|
|
3276
3271
|
// Wait for pending writes to complete
|
|
3277
3272
|
try {
|
|
3278
3273
|
await this._writeChain;
|
|
3279
|
-
} catch
|
|
3280
|
-
// this.logger.debug(
|
|
3274
|
+
} catch {
|
|
3275
|
+
// this.logger.debug("Pending write error during disconnect");
|
|
3281
3276
|
}
|
|
3282
3277
|
|
|
3283
3278
|
// Release persistent writer before closing
|
|
@@ -3285,8 +3280,8 @@ export class ESPLoader extends EventTarget {
|
|
|
3285
3280
|
try {
|
|
3286
3281
|
await this._writer.close();
|
|
3287
3282
|
this._writer.releaseLock();
|
|
3288
|
-
} catch
|
|
3289
|
-
// this.logger.debug(
|
|
3283
|
+
} catch {
|
|
3284
|
+
// this.logger.debug("Writer close/release error");
|
|
3290
3285
|
}
|
|
3291
3286
|
this._writer = undefined;
|
|
3292
3287
|
} else {
|
|
@@ -3296,8 +3291,8 @@ export class ESPLoader extends EventTarget {
|
|
|
3296
3291
|
const writer = this.port.writable.getWriter();
|
|
3297
3292
|
await writer.close();
|
|
3298
3293
|
writer.releaseLock();
|
|
3299
|
-
} catch
|
|
3300
|
-
// this.logger.debug(
|
|
3294
|
+
} catch {
|
|
3295
|
+
// this.logger.debug("Direct writer close error");
|
|
3301
3296
|
}
|
|
3302
3297
|
}
|
|
3303
3298
|
|
|
@@ -3325,7 +3320,7 @@ export class ESPLoader extends EventTarget {
|
|
|
3325
3320
|
// Only cancel if reader is still active
|
|
3326
3321
|
try {
|
|
3327
3322
|
this._reader.cancel();
|
|
3328
|
-
} catch
|
|
3323
|
+
} catch {
|
|
3329
3324
|
// Reader already released, resolve immediately
|
|
3330
3325
|
clearTimeout(timeout);
|
|
3331
3326
|
resolve(undefined);
|
|
@@ -3356,8 +3351,8 @@ export class ESPLoader extends EventTarget {
|
|
|
3356
3351
|
// Wait for pending writes to complete
|
|
3357
3352
|
try {
|
|
3358
3353
|
await this._writeChain;
|
|
3359
|
-
} catch
|
|
3360
|
-
// this.logger.debug(
|
|
3354
|
+
} catch {
|
|
3355
|
+
// this.logger.debug("Pending write error during release");
|
|
3361
3356
|
}
|
|
3362
3357
|
|
|
3363
3358
|
// Release writer
|
|
@@ -3556,7 +3551,9 @@ export class ESPLoader extends EventTarget {
|
|
|
3556
3551
|
private async _ensureStreamsReady(): Promise<void> {
|
|
3557
3552
|
if (this.isWebUSB()) {
|
|
3558
3553
|
try {
|
|
3559
|
-
await (
|
|
3554
|
+
await (
|
|
3555
|
+
this.port as unknown as { recreateStreams(): Promise<void> }
|
|
3556
|
+
).recreateStreams();
|
|
3560
3557
|
this.logger.debug("WebUSB streams recreated");
|
|
3561
3558
|
|
|
3562
3559
|
let retries = 30;
|