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:
@@ -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],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user