Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da94cc6cdc | ||
|
|
70c88815cc |
@@ -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.11–30)...")
|
||||||
|
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:
|
||||||
|
|||||||
+1
-1
@@ -1079,7 +1079,7 @@ class UartMonitorWindow(ctk.CTkToplevel):
|
|||||||
ser.close()
|
ser.close()
|
||||||
self.after(0, self._on_open_success)
|
self.after(0, self._on_open_success)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.after(0, lambda: self._show_unavailable(str(e)))
|
self.after(0, lambda e=e: self._show_unavailable(str(e)))
|
||||||
|
|
||||||
threading.Thread(target=_bg_open, daemon=True).start()
|
threading.Thread(target=_bg_open, daemon=True).start()
|
||||||
|
|
||||||
|
|||||||
+26
-7
@@ -324,7 +324,7 @@ def _get_tool_version(tool_path: str) -> str:
|
|||||||
"""Get the version string from a tool executable.
|
"""Get the version string from a tool executable.
|
||||||
|
|
||||||
Tries (in order):
|
Tries (in order):
|
||||||
1. tool -version
|
1. tool -version → parse version from output
|
||||||
2. Extract from path (e.g., .../Vitis/2023.2/bin/xsct → 2023.2)
|
2. Extract from path (e.g., .../Vitis/2023.2/bin/xsct → 2023.2)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -343,14 +343,17 @@ def _get_tool_version(tool_path: str) -> str:
|
|||||||
)
|
)
|
||||||
output = (result.stdout + result.stderr).strip()
|
output = (result.stdout + result.stderr).strip()
|
||||||
if output:
|
if output:
|
||||||
# Look for a version pattern in output
|
# Scan all lines for a version pattern (skip batch echo noise)
|
||||||
m = re.search(r"(\d{4}\.\d+(?:\.\d+)?)", output)
|
for raw_line in output.splitlines():
|
||||||
|
line = raw_line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
# Skip Windows batch echo noise
|
||||||
|
if _is_batch_noise(line):
|
||||||
|
continue
|
||||||
|
m = re.search(r"(\d{4}\.\d+(?:\.\d+)?)", line)
|
||||||
if m:
|
if m:
|
||||||
return m.group(1)
|
return m.group(1)
|
||||||
# Return first meaningful line (truncated)
|
|
||||||
line = output.split("\n")[0][:80]
|
|
||||||
if line and "usage" not in line.lower():
|
|
||||||
return line
|
|
||||||
except (subprocess.TimeoutExpired, OSError):
|
except (subprocess.TimeoutExpired, OSError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -358,6 +361,22 @@ def _get_tool_version(tool_path: str) -> str:
|
|||||||
return _version_from_path(tool_path)
|
return _version_from_path(tool_path)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_batch_noise(line: str) -> bool:
|
||||||
|
"""Check if a line is Windows batch script noise.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
line: A line of output text.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the line looks like batch echo/status noise.
|
||||||
|
"""
|
||||||
|
noise_patterns = [
|
||||||
|
r"^ECHO\s+(is\s+(on|off)|处于)", # ECHO is on/off (en+zh)
|
||||||
|
r"^[A-Z]:\\[^>]*>", # Prompt line like C:\path>
|
||||||
|
]
|
||||||
|
return any(re.search(p, line, re.IGNORECASE) for p in noise_patterns)
|
||||||
|
|
||||||
|
|
||||||
# ── Main check function ──────────────────────────────────────────────
|
# ── Main check function ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user