diff --git a/src/bitstream_programmer.py b/src/bitstream_programmer.py index b672a09..0b3c09a 100644 --- a/src/bitstream_programmer.py +++ b/src/bitstream_programmer.py @@ -37,6 +37,15 @@ ProgressCallback = Callable[[str, str], None] | None # ── Helpers ───────────────────────────────────────────────────────── +def _tcl_path(path: str | Path) -> str: + """Convert a filesystem path to TCL-safe format. + + TCL interprets backslashes as escape sequences (\\f, \\t, \\n). + Forward slashes work on all platforms including Windows. + """ + return str(path).replace("\\", "/") + + def _find_ps7_init_tcl(config: Config) -> str: """Find the ps7_init.tcl file for PS initialization. @@ -187,11 +196,11 @@ def _program_with_xsct( lines = ["connect"] if ps7_init_tcl and Path(ps7_init_tcl).exists(): lines.append("targets 1") - lines.append(f'source "{ps7_init_tcl}"') + lines.append(f'source "{_tcl_path(ps7_init_tcl)}"') lines.append("ps7_init") if callback: callback("progress", "PS initialized (clocks, DDR, MIO)") - lines.append(f'fpga -file "{bit_path}"') + lines.append(f'fpga -file {{{_tcl_path(bit_path)}}}') if ps7_init_tcl and Path(ps7_init_tcl).exists(): lines.append("ps7_post_config") if callback: @@ -381,13 +390,13 @@ def _run_elf_via_fsbl( tcl = "\n".join([ "connect", "targets 2", - "dow \"%s\"" % fsbl_path, + "dow {%s}" % _tcl_path(fsbl_path), "puts \"FSBL downloaded\"", "con", "after 3000", "stop", "puts \"FSBL done, CPU halted\"", - "dow \"%s\"" % elf_path, + "dow {%s}" % _tcl_path(elf_path), "mwr 0xF800025C 0x00000001", "con", "puts \"App running\"", @@ -461,7 +470,7 @@ def _run_elf_direct( tcl = "\n".join([ "connect", "targets 2", - "dow \"%s\"" % elf_path, + "dow {%s}" % _tcl_path(elf_path), "mwr 0xF800025C 0x00000001", "con", "exit", @@ -620,18 +629,18 @@ def full_bitstream_program( "rst -processor", "after 500", 'puts "INFO: Downloading FSBL..."', - 'dow "%s"' % fsbl_path, + 'dow {%s}' % _tcl_path(fsbl_path), 'puts "INFO: Running FSBL for hardware initialization..."', "con", "after 2000", "stop", 'puts "INFO: Hardware initialization completed."', 'puts "INFO: Downloading Bitstream..."', - 'fpga -f "%s"' % bit_path, + 'fpga -f {%s}' % _tcl_path(bit_path), "after 1000", 'targets -set -nocase -filter {name =~ "arm*#0"}', 'puts "INFO: Downloading Application ELF..."', - 'dow "%s"' % elf_path, + 'dow {%s}' % _tcl_path(elf_path), 'puts "INFO: Executing Application..."', "con", 'puts "SUCCESS: Zynq target is running the specified application."',