fix(uart): el hook de TX de la Pi se reinstala cuando nace el bridge

Las rutas serie se construyen al cargar la pagina, pero el bridge de una
placa QEMU-Linux nace al pulsar Run: ensureSerialHook encontraba bridge
nulo, hacia no-op y nadie volvia a intentarlo — los bytes que el guest
transmitia por el header salian del backend (uart_tx) y morian en un
onUartTx sin instalar. reensureSerialHooks(boardId) repite el enganche
(idempotente por el flag) y el store lo llama al crear el bridge.
This commit is contained in:
David Montero Crespo 2026-07-29 17:26:02 +02:00
parent 93388c675a
commit c55e399055
2 changed files with 17 additions and 0 deletions

View File

@ -747,6 +747,18 @@ export function notifyBoardReady(_boardId: string, wires: readonly Wire[]): void
updateI2CBridges(wires); updateI2CBridges(wires);
} }
/**
* Re-attempt the serial hook for a board whose sim/bridge did not exist
* when the routes were built. Routes are installed at page load; a Pi's
* bridge is created at Run so the TX hook silently no-opped and the
* guest's UART bytes never reached the wire. The store calls this when
* the bridge connects; ensureSerialHook is idempotent via its flag.
*/
export function reensureSerialHooks(boardId: string): void {
const entry = boards.get(boardId);
if (entry && entry.serialFanout.size > 0) ensureSerialHook(entry);
}
/** For tests: reset all internal state. */ /** For tests: reset all internal state. */
export function resetInterconnect(): void { export function resetInterconnect(): void {
for (const r of routes.values()) r.teardown(); for (const r of routes.values()) r.teardown();

View File

@ -55,6 +55,7 @@ import { isBreadboard } from '../utils/breadboardNets';
import { computeSeating } from '../utils/breadboardSnap'; import { computeSeating } from '../utils/breadboardSnap';
import { createSerialBatcher } from './serialBatcher'; import { createSerialBatcher } from './serialBatcher';
import { import {
reensureSerialHooks as icReensureSerialHooks,
bindBoard as icBindBoard, bindBoard as icBindBoard,
unbindBoard as icUnbindBoard, unbindBoard as icUnbindBoard,
updateWires as icUpdateWires, updateWires as icUpdateWires,
@ -1344,6 +1345,10 @@ export const useSimulatorStore = create<SimulatorState>((set, get) => {
}); });
}; };
bridgeMap.set(id, bridge); bridgeMap.set(id, bridge);
// The UART routes were built at page load, when this bridge did
// not exist — re-attempt the TX hook now that it does, or the
// guest's header-UART bytes never reach the canvas wire.
icReensureSerialHooks(id);
} else if (isEsp32Kind(boardKind)) { } else if (isEsp32Kind(boardKind)) {
wireEsp32Board(id, boardKind, pm); wireEsp32Board(id, boardKind, pm);
} else if (isStm32BoardKind(boardKind)) { } else if (isStm32BoardKind(boardKind)) {