✨ feat: UART boot wait, serial validation, xsct logging, layout fix
Config: - Add boot_wait_delay (default 10s) for post-reboot wait time Layout: - Restore row weights for proportional scaling when maximized - CTkScrollableFrame handles overflow when window is small Step 3: - Log xsct/vivado tool output (last 20 lines per result) for detailed diagnostics Step 4: - UART boot wait: monitor for IP/version via UART after reboot - If UART unavailable, fall back to config.boot_wait_delay - Reduces unnecessary wait time when boot is detected early Serial: - Real-time port validation on selection change (CTkComboBox command) - Persistent UART unavailable warning until valid port selected - Auto-restart UART monitor on port switch - Graceful cross-platform handling
This commit is contained in:
@@ -268,6 +268,7 @@ class MainWindow(ctk.CTk):
|
||||
# Scrollable main container — scrollbar appears when content overflows
|
||||
main_frame = ctk.CTkScrollableFrame(self)
|
||||
main_frame.pack(fill="both", expand=True, padx=PADDING_LARGE, pady=PADDING_LARGE)
|
||||
main_frame.grid_rowconfigure(1, weight=1)
|
||||
main_frame.grid_columnconfigure(0, weight=1)
|
||||
|
||||
# ── Header ──
|
||||
@@ -285,6 +286,7 @@ class MainWindow(ctk.CTk):
|
||||
# ── Right Panel: Configuration ──
|
||||
right_frame = ctk.CTkFrame(main_frame)
|
||||
right_frame.grid(row=1, column=1, sticky="nsew", padx=(PADDING, 0))
|
||||
right_frame.grid_rowconfigure(3, weight=1)
|
||||
right_frame.grid_columnconfigure(0, weight=1)
|
||||
|
||||
self._build_config_panel(right_frame)
|
||||
@@ -622,6 +624,7 @@ class MainWindow(ctk.CTk):
|
||||
port_frame,
|
||||
values=[""] + [p.device for p in detect_serial_ports()],
|
||||
variable=self._port_var,
|
||||
command=self._on_port_changed,
|
||||
)
|
||||
self._port_menu.grid(row=0, column=1, sticky="nsew", padx=PADDING_SMALL)
|
||||
|
||||
@@ -852,6 +855,49 @@ class MainWindow(ctk.CTk):
|
||||
self._uart_warning_label.configure(text=msg)
|
||||
self._uart_warning_label.pack(fill="x", padx=PADDING, pady=(0, PADDING_SMALL))
|
||||
|
||||
def _hide_uart_warning(self) -> None:
|
||||
"""Hide the persistent UART warning label."""
|
||||
self._uart_warning_label.pack_forget()
|
||||
|
||||
def _on_port_changed(self, new_port: str) -> None:
|
||||
"""Handle serial port selection change — validate immediately.
|
||||
|
||||
Args:
|
||||
new_port: The newly selected serial port path.
|
||||
"""
|
||||
if not new_port:
|
||||
self._uart_available = False
|
||||
self._show_uart_notification("No port selected")
|
||||
if self._uart_monitor:
|
||||
self._stop_uart_monitor()
|
||||
return
|
||||
|
||||
# Attempt to open port to validate
|
||||
try:
|
||||
port = new_port
|
||||
baudrate = self._config.serial_baudrate if self._config else 115200
|
||||
available, reason = check_uart_available(port, baudrate)
|
||||
self._uart_available = available
|
||||
if available:
|
||||
self._uart_message = reason
|
||||
self._hide_uart_warning()
|
||||
self._log_message(f" ✓ UART {port}: {reason}")
|
||||
# If UART monitor was running, restart on new port
|
||||
if self._uart_monitor and self._uart_monitor.is_running():
|
||||
self._stop_uart_monitor()
|
||||
self._start_uart_monitor()
|
||||
else:
|
||||
self._uart_available = False
|
||||
self._uart_message = reason
|
||||
self._show_uart_notification(reason)
|
||||
if self._uart_monitor:
|
||||
self._stop_uart_monitor()
|
||||
except Exception as e:
|
||||
self._uart_available = False
|
||||
self._show_uart_notification(str(e))
|
||||
if self._uart_monitor:
|
||||
self._stop_uart_monitor()
|
||||
|
||||
def _run_step_2_program_flash(self) -> bool:
|
||||
"""Step 2: Program and verify Flash using program_flash."""
|
||||
if not self._config:
|
||||
@@ -937,6 +983,11 @@ class MainWindow(ctk.CTk):
|
||||
for result in results:
|
||||
status = "✓" if result.success else "✗"
|
||||
self._log_message(f" {status} {result.step}: {result.message}")
|
||||
if result.output:
|
||||
# Log tool output for diagnostics (truncated)
|
||||
output_lines = result.output.strip().splitlines()
|
||||
for line in output_lines[-20:]: # last 20 lines
|
||||
self._log_message(f" [xsct] {line}")
|
||||
if "DAP" in result.message and not result.success:
|
||||
dap_fail = True
|
||||
|
||||
@@ -1077,6 +1128,29 @@ class MainWindow(ctk.CTk):
|
||||
self._log_message(" Skipping boot verify (reboot failed)")
|
||||
return False
|
||||
|
||||
# Wait for board to boot — UART if available, else config delay
|
||||
boot_delay = self._config.boot_wait_delay
|
||||
uart_alive = (self._uart_monitor is not None
|
||||
and self._uart_monitor.is_running())
|
||||
if uart_alive:
|
||||
self._log_message(f" ⏳ Waiting for UART boot signal (max {boot_delay}s)...")
|
||||
elapsed = 0.0
|
||||
while elapsed < boot_delay:
|
||||
info = self._uart_monitor.latest_info
|
||||
if info.ip_address or info.version:
|
||||
self._log_message(
|
||||
f" ✓ Boot detected after {elapsed:.1f}s"
|
||||
f" (IP={info.ip_address}, Ver={info.version})"
|
||||
)
|
||||
break
|
||||
time.sleep(0.5)
|
||||
elapsed += 0.5
|
||||
else:
|
||||
self._log_message(f" ⏱ UART timeout — no boot signal in {boot_delay}s")
|
||||
else:
|
||||
self._log_message(f" ⏳ UART unavailable — sleeping {boot_delay}s for boot...")
|
||||
time.sleep(boot_delay)
|
||||
|
||||
# 4e: Verify boot
|
||||
self._log_message("Step 4e: Verifying boot...")
|
||||
if hasattr(self, '_tftp_sub_step_frame'):
|
||||
|
||||
Reference in New Issue
Block a user