fix: use xsct (not Vivado) for JTAG check + normalize COM>=10 ports on Windows
**JTAG check**: Switch from Vivado to xsct - xsct is already proven to work (JTAG reboot succeeds) - Much lighter than Vivado (no GUI infrastructure / open_hw_manager) - Uses -eval inline TCL: connect; targets; disconnect; quit - Removes dead tempfile/Path/os imports **Windows COM port**: Add normalize_port() to serial_monitor.py - COM ports >= 10 require NT namespace prefix (\.\COM11) - Without it: PermissionError(13, '拒绝访问。') - Applied at all 7 call sites: serial_monitor (5), reboot_manager, widgets
This commit is contained in:
+25
-30
@@ -8,17 +8,14 @@ recognition on the JTAG chain.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
|
||||
from config_manager import Config
|
||||
from vitis_checker import get_vivado_path, get_hw_server_path, build_tool_command
|
||||
from vitis_checker import get_xsct_path, get_hw_server_path, build_tool_command
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -102,35 +99,32 @@ def check_zynq_jtag(config: Config, callback: Callable | None = None) -> ZynqChe
|
||||
|
||||
hw_proc: subprocess.Popen | None = None
|
||||
try:
|
||||
# Start hw_server in the background (it daemonises own I/O)
|
||||
# Start hw_server in the background (needed for xsct connect)
|
||||
hw_proc = subprocess.Popen(
|
||||
build_tool_command(hw_server_path),
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
# Give hw_server a moment to bind its port
|
||||
time.sleep(2)
|
||||
time.sleep(2) # let hw_server bind its port
|
||||
|
||||
# ── 2. Find vivado ────────────────────────────────────
|
||||
vivado_path = get_vivado_path(xilinx_root=xilinx_root)
|
||||
if not vivado_path:
|
||||
# ── 2. Find xsct (much lighter than Vivado for JTAG ops) ──
|
||||
xsct_path = get_xsct_path(xilinx_root=xilinx_root)
|
||||
if not xsct_path:
|
||||
return ZynqCheckResult(
|
||||
devices=[], jtag_chain=[], is_present=False,
|
||||
ps_detected=False, pl_detected=False,
|
||||
hw_server_url=hw_server_url,
|
||||
error="Vivado not found",
|
||||
error="xsct not found",
|
||||
)
|
||||
|
||||
# ── 3. Create and run JTAG query TCL ──────────────────
|
||||
# ── 3. Run JTAG query TCL via xsct ────────────────────
|
||||
tcl_content = _build_jtag_query_tcl()
|
||||
tcl_path = Path(tempfile.gettempdir()) / f"zynq_jtag_check_{os.getpid()}.tcl"
|
||||
tcl_path.write_text(tcl_content)
|
||||
|
||||
if callback:
|
||||
callback("progress", "Scanning JTAG chain...")
|
||||
|
||||
cmd = build_tool_command(
|
||||
vivado_path, "-mode", "batch", "-source", str(tcl_path),
|
||||
xsct_path, "-eval", tcl_content,
|
||||
)
|
||||
python_timeout = config.step_timeouts.get("check_env", 120)
|
||||
result = subprocess.run(
|
||||
@@ -139,7 +133,6 @@ def check_zynq_jtag(config: Config, callback: Callable | None = None) -> ZynqChe
|
||||
text=True,
|
||||
timeout=python_timeout,
|
||||
)
|
||||
tcl_path.unlink(missing_ok=True)
|
||||
|
||||
output = result.stdout + result.stderr
|
||||
jtag_chain = _parse_jtag_chain(output)
|
||||
@@ -193,23 +186,25 @@ def check_zynq_jtag(config: Config, callback: Callable | None = None) -> ZynqChe
|
||||
|
||||
|
||||
def _build_jtag_query_tcl() -> str:
|
||||
"""Build TCL script for JTAG device query.
|
||||
"""Build TCL script for xsct JTAG device query.
|
||||
|
||||
Uses xsct (not Vivado) because:
|
||||
- xsct is much lighter (no GUI infrastructure)
|
||||
- xsct JTAG reboot already works on this system
|
||||
- connect + targets lists all devices on the JTAG chain
|
||||
|
||||
Returns:
|
||||
TCL script content as string.
|
||||
TCL script content as string (semicolon-delimited for -eval mode).
|
||||
"""
|
||||
return """
|
||||
open_hw_manager
|
||||
connect_hw_server
|
||||
open_hw_target
|
||||
puts "===JTAG_START==="
|
||||
foreach dev [get_hw_devices] {
|
||||
set name [get_property NAME $dev]
|
||||
puts "DEVICE:$name"
|
||||
}
|
||||
puts "===JTAG_END==="
|
||||
quit
|
||||
"""
|
||||
return (
|
||||
"connect; "
|
||||
'puts "===JTAG_START==="; '
|
||||
"set all [targets]; "
|
||||
'foreach t $all { puts "DEVICE:$t" }; '
|
||||
'puts "===JTAG_END==="; '
|
||||
"disconnect; "
|
||||
"quit"
|
||||
)
|
||||
|
||||
|
||||
def _parse_jtag_chain(output: str) -> list[JtagDevice]:
|
||||
|
||||
Reference in New Issue
Block a user