diff --git a/fpga_io.cpp b/fpga_io.cpp index 45c91f51b..994f9e8d2 100644 --- a/fpga_io.cpp +++ b/fpga_io.cpp @@ -427,6 +427,10 @@ static int make_env(const char *name, const char *cfg) int fpga_load_rbf(const char *name, const char *cfg, const char *xml) { + // Tear down the launcher frontend (and its HPS framebuffer mmaps) before any + // FPGA reconfiguration. A live frontend scanning out /dev/fb0 over the f2sdram + // bridge deadlocks the AXI bus when do_bridge(0) resets it during load. + alt_launcher_shutdown(); OsdDisable(); static char path[1024]; int ret = 0; diff --git a/support/zaparoo/alt_launcher.cpp b/support/zaparoo/alt_launcher.cpp index a9529b24e..3d03ced4b 100644 --- a/support/zaparoo/alt_launcher.cpp +++ b/support/zaparoo/alt_launcher.cpp @@ -17,9 +17,11 @@ #include #include "cfg.h" #include "file_io.h" +#include "fpga_io.h" #include "hardware.h" #include "input.h" #include "menu.h" +#include "scheduler.h" #include "shmem.h" #include "user_io.h" #include "video.h" @@ -472,10 +474,37 @@ static void exec_launcher_child(const char *path) _exit(1); } +// Bounded replacement for video_chvt(): its VT_WAITACTIVE blocks forever if the +// frontend stalls bringing up video, which would wedge the poll cothread. +static void switch_to_launcher_vt(void) +{ + int fd = open("/dev/tty0", O_RDONLY | O_CLOEXEC); + if (fd < 0) return; + + if (ioctl(fd, VT_ACTIVATE, s_vt)) printf("alt_launcher: VT_ACTIVATE fails\n"); + + // Yield to the scheduler rather than usleep() so the poll cothread stays + // cooperative while we wait (bounded) for the VT to become active. + unsigned long deadline = GetTimer(500); + for (;;) + { + struct vt_stat st; + if (!ioctl(fd, VT_GETSTATE, &st) && st.v_active == s_vt) break; + if (CheckTimer(deadline)) break; + scheduler_yield(); + } + + close(fd); +} + static void finalize_spawn(void) { + // Defer the VT/fb takeover until the FPGA/HDMI has settled; s_tty_deadline + // stays armed so this retries on a later alt_launcher_poll pass. + if (!is_fpga_ready(1)) return; + s_tty_deadline = 0; - video_chvt(s_vt); + switch_to_launcher_vt(); if (!s_native_crt) video_fb_enable(1); else