feat: DAP error detection and recovery in Step 3 TCL

- 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'
This commit is contained in:
Jeremy Shen
2026-06-10 17:52:14 +08:00
parent 0568315b83
commit 73b8225a27
+53 -9
View File
@@ -589,30 +589,56 @@ def full_bitstream_program(
if callback: if callback:
callback("start", "Initializing Zynq via JTAG (FSBL override)...") 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..."', 'puts "INFO: Starting Zynq initialization via JTAG override..."',
"connect", "connect",
"after 500", "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"}', 'targets -set -nocase -filter {name =~ "arm*#0"}',
# 2. Reset processor (bypass BootROM Flash boot)
'puts "INFO: Resetting processor (Bypassing BootROM Flash boot)..."', 'puts "INFO: Resetting processor (Bypassing BootROM Flash boot)..."',
"rst -processor", "rst -processor",
"after 500", "after 500",
# 3. Download FSBL to OCM
'puts "INFO: Downloading FSBL..."', 'puts "INFO: Downloading FSBL..."',
'dow "%s"' % fsbl_path, 'dow "%s"' % fsbl_path,
# 4. Run FSBL for hardware init (clocks, DDR, MIO)
'puts "INFO: Running FSBL for hardware initialization..."', 'puts "INFO: Running FSBL for hardware initialization..."',
"con", "con",
"after 2000", "after 2000",
"stop", "stop",
'puts "INFO: Hardware initialization completed."', 'puts "INFO: Hardware initialization completed."',
# 5. Program PL bitstream
'puts "INFO: Downloading Bitstream..."', 'puts "INFO: Downloading Bitstream..."',
'fpga -f "%s"' % bit_path, 'fpga -f "%s"' % bit_path,
"after 1000", "after 1000",
# 6. Back to ARM Core 0, download and run app
'targets -set -nocase -filter {name =~ "arm*#0"}', 'targets -set -nocase -filter {name =~ "arm*#0"}',
'puts "INFO: Downloading Application ELF..."', 'puts "INFO: Downloading Application ELF..."',
'dow "%s"' % elf_path, 'dow "%s"' % elf_path,
@@ -622,6 +648,8 @@ def full_bitstream_program(
"exit", "exit",
]) ])
tcl = "\n".join(tcl_lines)
with tempfile.NamedTemporaryFile( with tempfile.NamedTemporaryFile(
mode="w", suffix=".tcl", delete=False mode="w", suffix=".tcl", delete=False
) as tf: ) as tf:
@@ -644,6 +672,14 @@ def full_bitstream_program(
success = result.returncode == 0 and "SUCCESS" in output 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: if callback:
callback( callback(
"complete" if success else "error", "complete" if success else "error",
@@ -654,13 +690,21 @@ def full_bitstream_program(
BitstreamResult( BitstreamResult(
step="bitstream", step="bitstream",
success=success, 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], output=output[:4000],
), ),
BitstreamResult( BitstreamResult(
step="elf", step="elf",
success=success, 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], output=output[:4000],
), ),
] ]