Compare commits

...
2 Commits
Author SHA1 Message Date
yuysh 1619dc194f fix: two-phase boot wait — don't stop on version when IP still pending
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)
2026-06-11 15:41:21 +08:00
yuysh 267cae93b6 fix: use tempfile.gettempdir() instead of hardcoded /tmp/ for JTAG TCL file
/tmp/ doesn't exist on Windows — Path('/tmp/...') resolves to C:\tmp\ which
fails with 'No such file or directory'. Use tempfile.gettempdir() for
cross-platform temp directory resolution.

Also cleaned up the get_vivado_path() call (removed obsolete vitis_path kwarg).
2026-06-11 15:36:04 +08:00
2 changed files with 43 additions and 5 deletions
+41 -3
View File
@@ -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.1130)...")
discovered_ip = self._discover_zynq_ip()
if discovered_ip:
+2 -2
View File
@@ -11,6 +11,7 @@ from __future__ import annotations
import os
import re
import subprocess
import tempfile
from dataclasses import dataclass, field
from pathlib import Path
from typing import Callable
@@ -88,7 +89,6 @@ def check_zynq_jtag(config: Config, callback: Callable | None = None) -> ZynqChe
# Find vivado executable via Xilinx root scan
vivado_path = get_vivado_path(
vitis_path=getattr(config, "vitis_path", ""),
xilinx_root=getattr(config, "xilinx_path", ""),
)
if not vivado_path:
@@ -104,7 +104,7 @@ def check_zynq_jtag(config: Config, callback: Callable | None = None) -> ZynqChe
# Create temporary TCL script
tcl_content = _build_jtag_query_tcl()
tcl_path = Path("/tmp/zynq_jtag_check_{}.tcl".format(os.getpid()))
tcl_path = Path(tempfile.gettempdir()) / f"zynq_jtag_check_{os.getpid()}.tcl"
try:
tcl_path.write_text(tcl_content)