feat: auto-discover Zynq IP after reboot (UART or UDP scan)

After Step 4 reboot, the Zynq may obtain a different IP via DHCP.

IP discovery strategy:
1. UART available → parse IP from boot output (fast, zero network traffic)
2. UART unavailable → scan 192.168.100.11–30 via UDP ver() probe
   (port = last_octet - 3, 0.5s timeout each, ~10s max for 20 IPs)

If IP changed → auto-update config.zynq_ip + UI field
This commit is contained in:
2026-06-11 15:11:59 +08:00
parent 32b201cf8e
commit 70c88815cc
+40
View File
@@ -1146,6 +1146,7 @@ class MainWindow(ctk.CTk):
boot_delay = self._config.boot_wait_delay boot_delay = self._config.boot_wait_delay
uart_alive = (self._uart_monitor is not None uart_alive = (self._uart_monitor is not None
and self._uart_monitor.is_running()) and self._uart_monitor.is_running())
discovered_ip: str = ""
if uart_alive: if uart_alive:
self._log_message(f" ⏳ Waiting for UART boot signal (max {boot_delay}s)...") self._log_message(f" ⏳ Waiting for UART boot signal (max {boot_delay}s)...")
elapsed = 0.0 elapsed = 0.0
@@ -1156,6 +1157,7 @@ class MainWindow(ctk.CTk):
f" ✓ Boot detected after {elapsed:.1f}s" f" ✓ Boot detected after {elapsed:.1f}s"
f" (IP={info.ip_address}, Ver={info.version})" f" (IP={info.ip_address}, Ver={info.version})"
) )
discovered_ip = info.ip_address
break break
time.sleep(0.5) time.sleep(0.5)
elapsed += 0.5 elapsed += 0.5
@@ -1165,6 +1167,23 @@ class MainWindow(ctk.CTk):
self._log_message(f" ⏳ UART unavailable — sleeping {boot_delay}s for boot...") self._log_message(f" ⏳ UART unavailable — sleeping {boot_delay}s for boot...")
time.sleep(boot_delay) time.sleep(boot_delay)
# Discover actual IP after reboot (may have changed via DHCP)
if not discovered_ip:
self._log_message(" Scanning for Zynq IP (192.168.100.1130)...")
discovered_ip = self._discover_zynq_ip()
if discovered_ip:
self._log_message(f" ✓ Found Zynq at {discovered_ip}")
else:
self._log_message(" ⚠ Zynq not found on any scanned IP")
if discovered_ip and discovered_ip != self._config.zynq_ip:
self._log_message(
f" IP changed: {self._config.zynq_ip}{discovered_ip}"
)
self._config.zynq_ip = discovered_ip
if self._ip_string_var:
self._ip_string_var.set(discovered_ip)
# 4e: Verify boot # 4e: Verify boot
self._log_message("Step 4e: Verifying boot...") self._log_message("Step 4e: Verifying boot...")
if hasattr(self, '_tftp_sub_step_frame'): if hasattr(self, '_tftp_sub_step_frame'):
@@ -1655,6 +1674,27 @@ class MainWindow(ctk.CTk):
threading.Thread(target=_thread, daemon=True).start() threading.Thread(target=_thread, daemon=True).start()
def _discover_zynq_ip(self) -> str:
"""Scan IP range to find the Zynq after reboot.
Sends UDP ver() to each candidate IP (port = last_octet - 3)
and returns the first IP that responds.
Returns:
Discovered IP address, or empty string if not found.
"""
subnet = "192.168.100"
for last in range(11, 31):
ip = f"{subnet}.{last}"
try:
from reboot_manager import _send_udp_command
ok, _resp = _send_udp_command(ip, b"ver()", timeout=0.5)
if ok:
return ip
except Exception:
continue
return ""
# ── Vitis Check ──────────────────────────────────────────── # ── Vitis Check ────────────────────────────────────────────
def _check_vitis(self) -> None: def _check_vitis(self) -> None: