From 1619dc194fd0d6a37f7237449a903a09845e4a54 Mon Sep 17 00:00:00 2001 From: Jeremy Shen Date: Thu, 11 Jun 2026 15:41:21 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20two-phase=20boot=20wait=20=E2=80=94=20do?= =?UTF-8?q?n't=20stop=20on=20version=20when=20IP=20still=20pending?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the boot wait loop broke on the first detection of EITHER IP or version. The Zynq firmware outputs its version string early in the boot sequence (e.g. firmware header), while the board IP arrives in a later burst via 'Boot=, IP=192.168.100.13, Ver=...'. The loop would break on the version-only signal, leaving IP empty. Changes: 1. Phase 1: log boot signal (version) but keep polling for IP 2. Phase 2: break only when IP address is actually found 3. After timeout: final check of latest_info for late-arriving IP 4. UART buffer fallback: parse all accumulated lines for IP (handles lines that arrived between the last poll and exit) 5. 3s pre-scan delay before UDP discover to let network stack settle (board's UDP server starts at the very end of boot sequence) --- src/gui/main_window.py | 44 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/src/gui/main_window.py b/src/gui/main_window.py index e71c663..2081c88 100644 --- a/src/gui/main_window.py +++ b/src/gui/main_window.py @@ -1158,25 +1158,63 @@ class MainWindow(ctk.CTk): if uart_alive and _uart_src: self._log_message(f" ⏳ Waiting for UART boot signal (max {boot_delay}s)...") elapsed = 0.0 + boot_seen = False # Phase 1 guard — log once, keep waiting for IP while elapsed < boot_delay: - info = _uart_src.latest_info if hasattr(_uart_src, 'latest_info') else _uart_src.get_latest_info() - if info and (info.ip_address or info.version): + info = ( + _uart_src.latest_info + if hasattr(_uart_src, "latest_info") + else _uart_src.get_latest_info() + ) + # Phase 2: IP address found — definitive boot confirmation + if info and info.ip_address: self._log_message( f" ✓ Boot detected after {elapsed:.1f}s" f" (IP={info.ip_address}, Ver={info.version})" ) discovered_ip = info.ip_address break + # Phase 1: boot signal (version) seen but no IP yet — keep polling + if info and info.version and not boot_seen: + boot_seen = True + self._log_message( + f" ✓ Boot signal after {elapsed:.1f}s" + f" (Ver={info.version}), waiting for IP..." + ) time.sleep(0.5) elapsed += 0.5 else: - self._log_message(f" ⏱ UART timeout — no boot signal in {boot_delay}s") + self._log_message(f" ⏱ UART timeout — no IP in {boot_delay}s") + # Final check: IP may have arrived after the last poll + info = ( + _uart_src.latest_info + if hasattr(_uart_src, "latest_info") + else _uart_src.get_latest_info() + ) + if info and info.ip_address: + self._log_message(f" IP recovered from latest UART info: {info.ip_address}") + discovered_ip = info.ip_address else: self._log_message(f" ⏳ UART unavailable — sleeping {boot_delay}s for boot...") time.sleep(boot_delay) + # Fallback: parse IP from accumulated UART buffer (lines may arrive + # after boot wait loop exited — e.g. "Board IP: 192.168.100.13") + if not discovered_ip and _uart_src: + all_lines = ( + _uart_src.all_lines + if hasattr(_uart_src, "all_lines") + else [] + ) + if all_lines: + parsed = parse_boot_output(all_lines) + if parsed.ip_address: + discovered_ip = parsed.ip_address + self._log_message(f" IP from UART buffer: {discovered_ip}") + # Discover actual IP after reboot (may have changed via DHCP) if not discovered_ip: + self._log_message(" ⏳ Network stack — waiting 3s...") + time.sleep(3) self._log_message(" Scanning for Zynq IP (192.168.100.11–30)...") discovered_ip = self._discover_zynq_ip() if discovered_ip: