✨ feat(uart): add UART availability check, inter-step delays, and post-download Zynq status verification
- Add check_uart_available() to serial_monitor.py — detects port availability - Add verify_zynq_status() to boot_verifier.py — lightweight post-download check - Add uart_delay / inter_step_delay config fields (defaults: 3s / 2s) - Step 1: Check UART availability, show non-blocking 'UART 不可用' notification - Step 4: Add post-download Zynq status check (ping + serial) after TFTP - _run_steps_worker: Add configurable inter-step delays between all steps - Update step labels (4a→4b→4c→4d) for clarity
This commit is contained in:
@@ -124,6 +124,100 @@ def verify_boot(
|
||||
)
|
||||
|
||||
|
||||
def verify_zynq_status(
|
||||
config: Config,
|
||||
timeout: int | None = None,
|
||||
max_retries: int = 3,
|
||||
uart_available: bool = True,
|
||||
callback: ProgressCallback = None,
|
||||
) -> BootVerificationResult:
|
||||
"""Quickly verify Zynq is responding after a download operation.
|
||||
|
||||
Performs a fast ping check and optionally a serial port read.
|
||||
Unlike verify_boot, this is a lightweight check meant to confirm
|
||||
the device is alive after flash/TFTP operations (before reboot).
|
||||
|
||||
Args:
|
||||
config: Application configuration.
|
||||
timeout: Seconds per ping attempt.
|
||||
max_retries: Number of ping retry attempts.
|
||||
uart_available: Whether UART serial port is available.
|
||||
callback: Optional progress callback.
|
||||
|
||||
Returns:
|
||||
BootVerificationResult (ip_reachable and serial_found reflect
|
||||
the quick check results).
|
||||
"""
|
||||
timeout = timeout or config.ping_timeout
|
||||
ip = config.zynq_ip
|
||||
|
||||
if callback:
|
||||
callback("start", f"Checking Zynq status on {ip}...")
|
||||
|
||||
# Check 1: Ping
|
||||
ip_reachable = False
|
||||
for attempt in range(1, max_retries + 1):
|
||||
if callback:
|
||||
callback("progress", f"Ping attempt {attempt}/{max_retries}...")
|
||||
if ping_ip(ip, 1, timeout):
|
||||
ip_reachable = True
|
||||
if callback:
|
||||
callback("complete", f"Device {ip} is reachable")
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
# Check 2: Serial (only if UART is available)
|
||||
serial_found = False
|
||||
boot_info: dict = {}
|
||||
if uart_available and config.serial_port:
|
||||
ports = detect_serial_ports()
|
||||
if ports:
|
||||
for port_info in ports:
|
||||
if port_info.device == config.serial_port:
|
||||
try:
|
||||
lines = read_serial_stream(
|
||||
config.serial_port,
|
||||
config.serial_baudrate,
|
||||
timeout=3,
|
||||
)
|
||||
parsed = parse_boot_output(lines)
|
||||
if parsed.ip_address or parsed.boot_message or parsed.version:
|
||||
serial_found = True
|
||||
boot_info = {
|
||||
"ip_address": parsed.ip_address,
|
||||
"version": parsed.version,
|
||||
"boot_message": parsed.boot_message,
|
||||
"raw_lines": lines[-20:],
|
||||
}
|
||||
if callback:
|
||||
callback("complete", "Boot messages detected on serial")
|
||||
break
|
||||
except Exception:
|
||||
pass # Non-fatal; fall through
|
||||
|
||||
success = ip_reachable or serial_found
|
||||
message_parts = []
|
||||
if ip_reachable:
|
||||
message_parts.append(f"IP {ip} reachable")
|
||||
if serial_found:
|
||||
message_parts.append("serial boot info found")
|
||||
if not success:
|
||||
message_parts.append("Zynq not responding")
|
||||
|
||||
message = "; ".join(message_parts) if message_parts else "Check inconclusive"
|
||||
|
||||
if callback:
|
||||
callback("complete" if success else "error", message)
|
||||
|
||||
return BootVerificationResult(
|
||||
success=success,
|
||||
message=message,
|
||||
ip_reachable=ip_reachable,
|
||||
serial_found=serial_found,
|
||||
boot_info=boot_info if boot_info else {},
|
||||
)
|
||||
|
||||
|
||||
def wait_for_boot(
|
||||
config: Config,
|
||||
timeout: int | None = None,
|
||||
|
||||
Reference in New Issue
Block a user