Windows backslashes in TCL strings are interpreted as escape sequences
(\f → form feed, \t → tab). This caused 'dow "Files\fsbl..."' to
fail with garbled paths — TCL couldn't find the file.
Added _tcl_path() helper: replaces \ with / in any path before
embedding in TCL. Forward slashes work on all platforms including
Windows. Applied to all 7 path sites: source, fpga -file, dow.
- Add preemptive rst -system at Step 3 start to clean post-flash DAP state
- Replace ineffective SLCR write with targets 1 → rst -system recovery
- Exit with clear power-cycle instructions when DAP recovery fails
- Show prominent DAP error guidance in GUI for Step 3 and Run All mode
Verified: Step 1→2→3 now passes end-to-end (340s) without board power cycle.
- TCL now checks for ARM core visibility before attempting flow
- If ARM cores are not found (DAP APB transaction error):
* Logs WARNING with target list
* Attempts SLCR system reset (0xF8000200)
* Reconnects after recovery attempt
- DAP errors detected in xsct output and logged to GUI log
- Result message shows 'DAP error — board needs power cycle'
1. Boot mode parsing:
- BootInfo.boot_mode field added
- Matches 'Boot mode is JTAG', 'Boot Mode: QSPI', etc.
- Fixed false version match: 'Boot mode is' no longer
captures 'mode' as a version string
2. UART window cleanup:
- Parsed boot info (mode/IP/ver) now only goes to main log
- Raw serial lines still appear in UART window
3. Step 3 FSBL enforcement:
- BIT step: after fpga -file, CPU is immediately halted (stop)
to prevent Flash code from enabling MMU
- ELF step: always dow FSBL → con → stop → dow bootloader
4. UI reorder:
- FSBL ELF selector moved BEFORE Bootloader BIT
- New layout: FSBL → BIT → ELF → Bootloader BIN → Flash → FW BIN
- Fixed grid overlap (FSBL and Flash were both at row 6)
Problem: dow app.elf to DDR (0x100000) failed with MMU section
translation fault because the CPU had MMU enabled from previously
executed Flash code. ps7_init could reset this but user wants
FSBL-based flow.
Fix: run_elf() now downloads FSBL first (to OCM 0x0 — always
accessible), runs it to initialize clocks/DDR/MIO and force JTAG
boot mode, then downloads the app ELF to DDR.
New flow:
connect → targets 2 → dow fsbl.elf → con → after 3s → stop
→ dow app.elf → mwr 0xF800025C 0x1 → con
Fallback: if no FSBL configured, use direct dow (legacy path).
Removed: _run_elf_with_xsct (2-attempt ps7_init recovery) replaced
by _run_elf_via_fsbl and _run_elf_direct.
Issue 1 — FirmWare version not parsed:
Input: [Info] FirmWare:V1.2.1.2.1_11_07_pmu_log3
Fix: regex [Ff]irm[Ww]are:?\s* (was [Ff]irmware\s+ — no : or camelCase)
Plus broader version capture: [Vv]\d+\.\d+\.\d+[^\s;,\n]*
Issue 2 — ELF loaded from Flash instead of downloaded ELF:
Root cause: Zynq devcfg.CTRL (0xF800025C) PCAP_PROG_B may trigger
reconfiguration from Flash after fpga, causing CPU to jump to
Flash-loaded code instead of our dow'd ELF.
BIT step: add ps7_post_config after fpga (finalizes PL-PS interfaces)
add mwr 0xF800025C 0x1 (disables PCAP reconfig)
ELF step: add mwr 0xF800025C 0x1 after dow, before con
(both attempt-1 and attempt-2 fallback)
Configuration panel now has a 'Xilinx Kit:' row at the top with:
- Entry field showing current path
- [Browse] button using system directory dialog (cross-platform)
- Select root directory (e.g. /data/xilinx or C:/Xilinx)
vitis_checker.py now scans xilinx_root subdirectories:
1. System PATH (shutil.which) — works on all platforms
2. Legacy vitis_path/bin
3. xilinx_root/Vitis/*/bin and Vivado/*/bin (all versions, newest first)
4. Common install paths (Windows: C:/Xilinx, Linux: /data/xilinx, /opt/xilinx)
Multi-version: scans all version directories under Vitis/ and Vivado/,
picks the newest version for each tool.
Config: xilinx_path replaces vitis_path (backward compat kept)
Based on real hardware timing data from XC7Z100 testing:
UART Monitoring:
- New UartMonitor class in serial_monitor.py: background thread reads
serial output continuously, parses for IP/version/boot messages
- GUI starts monitor when workflow runs, stops on completion/close
- Serial lines flow into log display in real time
Step Timing:
- New step_timeouts config (experience × 2):
check_env:30s flash_erase:120s flash_program:600s
bitstream:60s elf_download:60s tftp_reboot:120s
- GUI shows estimated timeout before each step
- Shows actual elapsed time after each step completes
- All subprocess calls now use config-driven timeouts
Non-blocking Output:
- New subprocess_utils.py: run_streaming() uses Popen + threaded
stdout/stderr readers, parses WARNING/ERROR/progress% in real time
- flash_programmer and bitstream_programmer use it
- Callbacks receive categorized events (out/err/warn/error/progress/done)
Fixes found during real hardware test:
bitstream_programmer.py:
- _program_with_xsct: use TCL file instead of xsct -eval (quit→exit fix)
- _run_elf_with_xsct: add reconnect + source ps7_init.tcl after PL config,
use target ID 2 instead of name filter, TCL file instead of -eval
- _find_ps7_init_tcl: auto-detect ps7_init.tcl from BIT file directory
- run_elf: remove Vivado fallback (program_hw_cpu is xsct, not Vivado)
- Remove dead _run_elf_with_vivado (Vivado HM can't program PS CPU)
flash_programmer.py:
- wipe_flash: -erase_only without -erase_all (s25fl256s1 compat fix)
- vitis_checker: shutil.which() + xsct fallback for impact detection
- flash_programmer: _get_impact_path now checks xsct as fallback
- bitstream_programmer: _get_impact_path now checks xsct as fallback
- GUI: show '(via xsct)' alias note when xsct replaces impact
- ToolStatus: add 'alias' field for tracking which executable was found