diff --git a/src/bitstream_programmer.py b/src/bitstream_programmer.py index bc28731..1ac4c6d 100644 --- a/src/bitstream_programmer.py +++ b/src/bitstream_programmer.py @@ -589,30 +589,56 @@ def full_bitstream_program( if callback: callback("start", "Initializing Zynq via JTAG (FSBL override)...") - tcl = "\n".join([ + # Build TCL with DAP error recovery + tcl_lines = [ 'puts "INFO: Starting Zynq initialization via JTAG override..."', "connect", "after 500", - # 1. Select ARM Core 0 + ] + + # DAP error check — if ARM cores not visible, try recovery + tcl_lines.extend([ + '# Check for DAP errors and attempt recovery', + 'set target_list [targets]', + 'set has_arm 0', + 'foreach t $target_list { if {[regexp -nocase {arm|cortex} $t]} { set has_arm 1 } }', + 'if {!$has_arm} {', + ' puts "WARNING: ARM cores not found — DAP may be in error state"', + ' # Show DAP status for logging', + ' foreach t $target_list { puts " TARGET: $t" }', + ' # Attempt to recover by reinitializing via DAP', + ' catch { targets 1 }', + ' after 500', + ' # If DAP is accessible, try writing to system reset register', + ' catch {', + ' puts "Attempting SLCR system reset..."', + ' mwr 0xF8000200 0x00000001', + ' after 1000', + ' disconnect', + ' after 1000', + ' connect', + ' after 500', + ' }', + '}', + '', + ]) + + # Core flow + tcl_lines.extend([ 'targets -set -nocase -filter {name =~ "arm*#0"}', - # 2. Reset processor (bypass BootROM Flash boot) 'puts "INFO: Resetting processor (Bypassing BootROM Flash boot)..."', "rst -processor", "after 500", - # 3. Download FSBL to OCM 'puts "INFO: Downloading FSBL..."', 'dow "%s"' % fsbl_path, - # 4. Run FSBL for hardware init (clocks, DDR, MIO) 'puts "INFO: Running FSBL for hardware initialization..."', "con", "after 2000", "stop", 'puts "INFO: Hardware initialization completed."', - # 5. Program PL bitstream 'puts "INFO: Downloading Bitstream..."', 'fpga -f "%s"' % bit_path, "after 1000", - # 6. Back to ARM Core 0, download and run app 'targets -set -nocase -filter {name =~ "arm*#0"}', 'puts "INFO: Downloading Application ELF..."', 'dow "%s"' % elf_path, @@ -622,6 +648,8 @@ def full_bitstream_program( "exit", ]) + tcl = "\n".join(tcl_lines) + with tempfile.NamedTemporaryFile( mode="w", suffix=".tcl", delete=False ) as tf: @@ -644,6 +672,14 @@ def full_bitstream_program( success = result.returncode == 0 and "SUCCESS" in output + # Detect DAP errors for logging + dap_errors = [l for l in output.split("\n") if "DAP" in l and "error" in l.lower()] + if dap_errors: + if callback: + for e in dap_errors: + callback("error", f"DAP: {e.strip()[:120]}") + success = False + if callback: callback( "complete" if success else "error", @@ -654,13 +690,21 @@ def full_bitstream_program( BitstreamResult( step="bitstream", success=success, - message="Bitstream loaded" if success else "Combined flow failed", + message=( + "DAP error — board needs power cycle" + if dap_errors else + "Bitstream loaded" if success else "Combined flow failed" + ), output=output[:4000], ), BitstreamResult( step="elf", success=success, - message="ELF executed" if success else "Combined flow failed", + message=( + "DAP error — board needs power cycle" + if dap_errors else + "ELF executed" if success else "Combined flow failed" + ), output=output[:4000], ), ]