fix(usb-deployer): CH340 port reuse fix — skip reopen, single DTR, baud tracking
This commit is contained in:
parent
2773bf2a83
commit
f164134222
|
|
@ -137,6 +137,7 @@ export class USBHardwareDeployer implements HardwareDeployer {
|
||||||
private keepReading = false;
|
private keepReading = false;
|
||||||
private _onDisconnected: (() => void) | null = null;
|
private _onDisconnected: (() => void) | null = null;
|
||||||
private _deviceName: string | null = null;
|
private _deviceName: string | null = null;
|
||||||
|
private currentBaudRate: number | null = null;
|
||||||
|
|
||||||
/* Bound handler so we can removeEventListener on cleanup */
|
/* Bound handler so we can removeEventListener on cleanup */
|
||||||
private _boundDisconnectHandler: ((event: SerialConnectionEvent) => void) | null = null;
|
private _boundDisconnectHandler: ((event: SerialConnectionEvent) => void) | null = null;
|
||||||
|
|
@ -188,6 +189,7 @@ export class USBHardwareDeployer implements HardwareDeployer {
|
||||||
parity: 'none',
|
parity: 'none',
|
||||||
flowControl: 'none'
|
flowControl: 'none'
|
||||||
});
|
});
|
||||||
|
this.currentBaudRate = FLASH_BAUD;
|
||||||
console.log('[USB] port opened at', FLASH_BAUD);
|
console.log('[USB] port opened at', FLASH_BAUD);
|
||||||
|
|
||||||
this.writer = this.port.writable!.getWriter();
|
this.writer = this.port.writable!.getWriter();
|
||||||
|
|
@ -209,21 +211,9 @@ export class USBHardwareDeployer implements HardwareDeployer {
|
||||||
async resetArduino(): Promise<void> {
|
async resetArduino(): Promise<void> {
|
||||||
if (!this.port) throw new Error('Belum terhubung ke perangkat');
|
if (!this.port) throw new Error('Belum terhubung ke perangkat');
|
||||||
|
|
||||||
console.log('[USB] resetArduino: Double DTR pulse sequence');
|
console.log('[USB] resetArduino: DTR/RTS pulse');
|
||||||
|
/* DTR low + RTS low → 50ms → both high → wait for optiboot.
|
||||||
/* Pulse 1 */
|
Longer low period (50ms vs 10ms) improves reliability on CH340 clones. */
|
||||||
await this.port.setSignals({
|
|
||||||
dataTerminalReady: false,
|
|
||||||
requestToSend: false
|
|
||||||
});
|
|
||||||
await sleep(50);
|
|
||||||
await this.port.setSignals({
|
|
||||||
dataTerminalReady: true,
|
|
||||||
requestToSend: true
|
|
||||||
});
|
|
||||||
await sleep(100);
|
|
||||||
|
|
||||||
/* Pulse 2 (Handshake) */
|
|
||||||
await this.port.setSignals({
|
await this.port.setSignals({
|
||||||
dataTerminalReady: false,
|
dataTerminalReady: false,
|
||||||
requestToSend: false
|
requestToSend: false
|
||||||
|
|
@ -234,8 +224,7 @@ export class USBHardwareDeployer implements HardwareDeployer {
|
||||||
requestToSend: true
|
requestToSend: true
|
||||||
});
|
});
|
||||||
await sleep(BOOTLOADER_SETTLE_MS);
|
await sleep(BOOTLOADER_SETTLE_MS);
|
||||||
|
console.log('[USB] resetArduino: DTR pulse done');
|
||||||
console.log('[USB] resetArduino: pulse sequence done');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Deploy ─────────────────────────────────────────────────── */
|
/* ── Deploy ─────────────────────────────────────────────────── */
|
||||||
|
|
@ -281,6 +270,7 @@ export class USBHardwareDeployer implements HardwareDeployer {
|
||||||
flowControl: 'none'
|
flowControl: 'none'
|
||||||
});
|
});
|
||||||
console.log('[USB-SERIAL] port opened at', SERIAL_MONITOR_BAUD);
|
console.log('[USB-SERIAL] port opened at', SERIAL_MONITOR_BAUD);
|
||||||
|
this.currentBaudRate = SERIAL_MONITOR_BAUD;
|
||||||
|
|
||||||
this.writer = this.port.writable!.getWriter();
|
this.writer = this.port.writable!.getWriter();
|
||||||
this.reader = this.port.readable!.getReader();
|
this.reader = this.port.readable!.getReader();
|
||||||
|
|
@ -339,6 +329,7 @@ export class USBHardwareDeployer implements HardwareDeployer {
|
||||||
this.writer = this.port.writable!.getWriter();
|
this.writer = this.port.writable!.getWriter();
|
||||||
this.reader = this.port.readable!.getReader();
|
this.reader = this.port.readable!.getReader();
|
||||||
console.log('[USB-SERIAL] baud rate changed to', baud);
|
console.log('[USB-SERIAL] baud rate changed to', baud);
|
||||||
|
this.currentBaudRate = baud;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Disconnect / lifecycle ─────────────────────────────────── */
|
/* ── Disconnect / lifecycle ─────────────────────────────────── */
|
||||||
|
|
@ -358,6 +349,14 @@ export class USBHardwareDeployer implements HardwareDeployer {
|
||||||
this.keepReading = false;
|
this.keepReading = false;
|
||||||
try {
|
try {
|
||||||
await this.reader?.cancel();
|
await this.reader?.cancel();
|
||||||
|
/* Wait for reader lock to release before close */
|
||||||
|
if (this.reader) {
|
||||||
|
try {
|
||||||
|
await this.reader.closed.catch(() => {});
|
||||||
|
} catch {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
|
|
@ -380,6 +379,7 @@ export class USBHardwareDeployer implements HardwareDeployer {
|
||||||
}
|
}
|
||||||
this.keepReading = false;
|
this.keepReading = false;
|
||||||
await this.stopReaderWriter();
|
await this.stopReaderWriter();
|
||||||
|
this.currentBaudRate = null;
|
||||||
try {
|
try {
|
||||||
await this.port?.close();
|
await this.port?.close();
|
||||||
} catch {
|
} catch {
|
||||||
|
|
@ -430,7 +430,6 @@ export class USBHardwareDeployer implements HardwareDeployer {
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.withTimeout(this.writer.write(cmd), timeoutMs, 'write');
|
await this.withTimeout(this.writer.write(cmd), timeoutMs, 'write');
|
||||||
await sleep(50);
|
|
||||||
console.log('[USB] write done');
|
console.log('[USB] write done');
|
||||||
|
|
||||||
/* Read STK_INSYNC (1 byte) */
|
/* Read STK_INSYNC (1 byte) */
|
||||||
|
|
@ -643,25 +642,38 @@ export class USBHardwareDeployer implements HardwareDeployer {
|
||||||
completedChunks: 0
|
completedChunks: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ── Ensure port is at flash baud rate (I4) ── */
|
/* ── Ensure port is at flash baud rate ── */
|
||||||
this.stopSerialMonitor();
|
this.stopSerialMonitor();
|
||||||
await this.stopReaderWriter();
|
await this.stopReaderWriter();
|
||||||
|
|
||||||
if (!this.port) {
|
if (!this.port) {
|
||||||
throw new Error('Port tidak tersedia — hubungkan perangkat terlebih dahulu');
|
throw new Error('Port tidak tersedia — hubungkan perangkat terlebih dahulu');
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
await this.port.close();
|
/* Reuse port if already at FLASH_BAUD. Closing+opening causes kernel
|
||||||
} catch {
|
DTR toggle on CH340/CH341 clones, which can make the bootloader
|
||||||
/* may already be closed */
|
exit before we get to resetArduino(). */
|
||||||
|
const needReopen = this.currentBaudRate !== FLASH_BAUD;
|
||||||
|
|
||||||
|
if (needReopen) {
|
||||||
|
try {
|
||||||
|
await this.port.close();
|
||||||
|
} catch {
|
||||||
|
/* may already be closed */
|
||||||
|
}
|
||||||
|
await this.port.open({
|
||||||
|
baudRate: FLASH_BAUD,
|
||||||
|
dataBits: 8,
|
||||||
|
stopBits: 1,
|
||||||
|
parity: 'none',
|
||||||
|
flowControl: 'none'
|
||||||
|
});
|
||||||
|
this.currentBaudRate = FLASH_BAUD;
|
||||||
|
console.log('[USB] flashBuffer: port reopened at', FLASH_BAUD);
|
||||||
|
} else {
|
||||||
|
console.log('[USB] flashBuffer: reusing existing port at', FLASH_BAUD);
|
||||||
}
|
}
|
||||||
await this.port.open({
|
|
||||||
baudRate: FLASH_BAUD,
|
|
||||||
dataBits: 8,
|
|
||||||
stopBits: 1,
|
|
||||||
parity: 'none',
|
|
||||||
flowControl: 'none'
|
|
||||||
});
|
|
||||||
console.log('[USB] flashBuffer: port reopened at', FLASH_BAUD);
|
|
||||||
this.writer = this.port.writable!.getWriter();
|
this.writer = this.port.writable!.getWriter();
|
||||||
this.reader = this.port.readable!.getReader();
|
this.reader = this.port.readable!.getReader();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue