pyserial should auto-add \\.\ prefix for COM>=10, but some versions
don't. Added _open_serial() helper that tries the raw port name first,
then falls back to explicit NT namespace prefix on Windows.
Replaces all serial.Serial() calls across serial_monitor, reboot_manager,
and widgets.
JTAG: Start hw_server explicitly (Windows needs it), then run Vivado
TCL with Popen + line-by-line stdout streaming via callback so user
can see Vivado progress in real-time (not just on failure).
COM: Remove normalize_port — pyserial >= 3.0 handles COM>=10 prefix
internally. The manual \\.\ prefix was causing PermissionError(13)
on Windows where pyserial's own handling conflicted.
**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
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)
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)
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)
- Add test_serial_version() to serial_monitor.py
- Sends 'ver()' command and parses version response
- Add 'Test Version' button in serial panel
- Displays version in status and log