Files
skills-win/zynq-imx6-flow/SKILL.md
T
2026-07-27 01:08:42 +08:00

11 KiB
Raw Blame History

name, description
name description
zynq-imx6-flow Run the zynq-imx6-flow LangGraph workflow at E:\LangGraph_Design\zynq-imx6-flow — the closed-loop xmod (Zynq PS+PL + i.MX6) hardware-in-the-loop design/debug pipeline: cold power-cycle, connect JTAG, program bitstream/ELF or burn flash, restart the ps/imx6 app, analyze (ILA + PS/imx6 serial consoles), judge against design requirements, and iterate by modifying RTL / imx6 app / PS baremetal code. It drives the graph in-process (no langgraph dev) and hands the 6 interrupts (analyze / meets_requirement / propose / modify_fpga / modify_imx6 / modify_ps) back to this Claude session to execute. Also supports zynq-only boards (no i.MX6) and PS baremetal/petalinux modes. ALWAYS use this skill whenever the user wants to run, start, drive, resume, or continue the zynq-imx6-flow workflow / xmod Zynq+imx6 design loop, or says things like "启动 zynq-imx6-flow", "跑 zynq 设计流程", "run the zynq FPGA flow", "执行 xmod 设计任务", "继续 zynq 工作流", "resume the zynq design loop", even if they don't name the project path. Before driving, this skill confirms the langgraph conda env from /langgraph-vivado-install is in place.

What this skill does

Drives the zynq-imx6-flow graph (28 nodes / 39 flow-edges, 1:1 with Notes/zynq-imx6-flow.excalidraw, plan Notes/Task00.md). The deterministic hardware/check nodes (power, JTAG, program, restart) run in-process; the 6 interrupt nodes pause and hand control to this Claude session, which does the real work (analysis, judgment, RTL/app/PS edits) and resumes the same thread. Persistence is a SqliteSaver file, so start/resume survive across separate process calls.

Item Value
Project root 见 ~\skills_env.md 的 ZYNQ_IMX6_FLOW_ROOT(driver 自动读取,也可 --project-dir 覆盖)
Conda env langgraph (path 见 ~\skills_env.md 的 CONDA_LANGGRAPH_PYTHON;装环境用 /langgraph-vivado-install)
Graph app.main_graph:build_graph (in-process; no langgraph dev)
Driver %USERPROFILE%\.claude\skills\zynq-imx6-flow\scripts\run_zynq_flow.py
Checkpoint <project>\runs\skill_checkpoint.sqlite (keyed by --thread-id)

Drive the driver with the Bash tool (Git Bash), not PowerShell. Windows PowerShell 5.1 strips the double-quotes out of --resume-json payloads (see Gotchas), corrupting the JSON. Git Bash single-quoting passes it intact. All commands below are Bash and were run this way to verify them.

PY="/c/Users/Administrator/miniconda3/envs/langgraph/python.exe"
RUN="/c/Users/Administrator/.claude/skills/zynq-imx6-flow/scripts/run_zynq_flow.py"
export PYTHONIOENCODING=utf-8

⚠️ Hardware timing rule (power / USB-Blast)

Before every power change to the board, USB-Blast must already be disconnected; only reconnect JTAG after power is up. Never power the board up/down while USB-Blast is connected (protects the JTAG adapter and board). The graph topology already enforces this: power_off → check_power_off →(是) blast_off_a → check_blast_off →(是) power_on → check_power →(是) blast_on → check_hw. After flash_burn the graph returns to power_off for a full cold-restart before re-analyzing. Serial port numbers are never hardcoded — they come from ~/zynq_imx6_flow.conf (see "Mock vs real").

Step 0 — Confirm the environment (REQUIRED before driving)

The workflow runs in the langgraph conda env created by /langgraph-vivado-install. Verify it first so a missing env is a clear message, not a cryptic mid-run import error:

"$PY" -c "from langgraph.checkpoint.sqlite import SqliteSaver; from langgraph.types import Command; import langgraph; print('[OK] langgraph')"
  • [OK] → proceed.
  • import fails / no python → tell the user to run /langgraph-vivado-install first (it creates the langgraph env with langgraph + langgraph-checkpoint-sqlite). Do not proceed until it succeeds.

Optional sanity check — the project's own acceptance suite (all mock, ~2 s):

cd /e/LangGraph_Design/zynq-imx6-flow && "$PY" smoke_test.py   # prints [PASS]

Step 1 — Start the workflow

Pick the board + first-pass program mode (defaults shown), then start on a fresh --thread-id:

"$PY" "$RUN" start --thread-id zynq-<short-task-name> \
  --board-type xmod --ps-mode baremetal --program-mode bitstream --bit-path mock.bit
  • --board-type xmod (Zynq+i.MX6, default) | zynq_only (no i.MX6 — imx6 branch is skipped).
  • --ps-mode baremetal (default) | petalinux.
  • --program-mode bitstream (default, downloads bit → restart → analyze) | debug_flash (image already fused in flash → straight to analyze, no download).
  • --bit-path / --elf-path / --flash-path optional artifact paths.
  • Add --real only with hardware wired + board connected (default is MOCK — see below).

The driver prints one JSON line and exits:

Exit status Meaning
0 done Workflow finished (符合要求 / iteration cap) → Step 3
1 error Read error, diagnose, report
2 interrupt An interrupt fired → read interrupt.action (and pending_count) → Step 2

Step 2 — Handle the interrupt(s), then resume

On exit 2, interrupt.action (or the pending_interrupts list) tells you what to do. Perform it, then resume the same --thread-id. Repeat until exit 0.

action excalidraw node What you (the session) do Resume JSON
analyze 通过ila/串口分析 Grab ILA + the sources consoles (ps_console, and imx6_console if xmod); summarize {"analysis_log":"<摘要/路径>"}
meets_requirement 符合设计要求? Judge analysis vs the design requirement {"meets": true} or {"meets": false}
propose 分析原因,提方案 Diagnose; review the plan with /langgraph-plan-review; decide what to change + next program mode {"reason":"...","need_fpga":bool,"need_imx6":bool,"need_ps":bool,"program_mode":"bitstream"或"flash"}
modify_fpga 改 RTL→综合→bit/flash Edit RTL, run Vivado synth/impl, produce bit + flash {"bit_path":"...","flash_path":"..."}
modify_imx6 VM 改 app→交叉编译 In the Ubuntu VM edit imx6 app + cross-compile {"app_path":"..."}
modify_ps sdk 改 PS 裸机→ELF In Xilinx SDK edit PS baremetal code + build (petalinux: rebuild app/image) {"elf_path":"..."}

Single interrupt — resume with the payload directly:

"$PY" "$RUN" resume --thread-id zynq-<name> --resume-json '{"meets": false}'

Three-way parallel fan-out — after a propose that sets need_fpga/need_imx6/ need_ps true, modify_fpga + modify_imx6 + modify_ps fire in one superstep (pending_count: 3). Resume them with one map keyed by action (subset allowed; unresumed ones stay pending and the deferred round_done still waits for every branch):

"$PY" "$RUN" resume --thread-id zynq-<name> --resume-json \
  '{"modify_fpga":{"bit_path":"new.bit","flash_path":"new.bin"},"modify_imx6":{"app_path":"new-app"},"modify_ps":{"elf_path":"new.elf"}}'

Notes:

  • Always reuse the same --thread-id from start — that's how the sqlite checkpoint reattaches (different tasks → different thread ids → isolated state).
  • propose fans out to decide_fpga/decide_imx6/decide_ps; all-false goes straight to round_done → re-program. board_type=zynq_only forces need_imx6=false.
  • program_mode from propose chooses the re-program path after round_done: bitstream = download bit; flash = burn flash then full cold power/connect re-sequence (flash_burn → power_off). This is the big closed loop.
  • "$PY" "$RUN" status --thread-id zynq-<name> re-prints the current state without advancing.

Step 3 — Finish

On exit 0 (status: done), report iterations completed and whether the design met requirements (meets_requirement) or hit the iteration cap. Offer to inspect <project>\runs\ artifacts or the per-step history.

To abandon a paused run and start clean, delete <project>\runs\skill_checkpoint.sqlite or use a fresh --thread-id.

Mock vs real

  • MOCK (default) — sets ZYNQ_IMX6_MOCK=1; hardware/check nodes return success immediately. Dry-runs the design-loop logic and all 6 interrupts with no board. Ideal for demonstrating/validating the flow. Every command in this doc was verified in mock.
  • Real (--real) — sets ZYNQ_IMX6_MOCK=0 and drives actual hardware. The tools_hw paths are wired (Modbus power relay 0x05, USB-Blast 0xA0 frames over pyserial). Real mode additionally requires:
    1. pyserial in the env ("$PY" -m pip install pyserial) — not installed by default; without it --real returns {"status":"error","error":"Real mode requires pyserial"}.
    2. ~/zynq_imx6_flow.conf with 4 sections [power] [usb_blast] [imx6_console] [ps_console] (template: project's zynq_imx6_flow.example.conf). Relay ports (power/usb_blast) may fall back to ~/vivado_mcp_usb.conf. zynq_only boards don't need [imx6_console]. COM numbers differ per machine — find them in Device Manager → Ports (COM & LPT).
    3. A connected board + Vivado for the JTAG program/flash nodes.

Gotchas

  • PowerShell 5.1 corrupts --resume-json. & $py $RUN resume --resume-json '{"meets": false}' arrives at Python as {meets: false} — PS strips the double-quotes (and \"-escaping splits it on spaces instead). This is the known PSNativeCommandArgumentPassing bug, unfixed in 5.1. Use the Bash tool. Verified: the same JSON through Git Bash arrives intact (analysis_log values with spaces round-trip correctly).
  • round_done is a deferred node (defer=True). With the three-way fan-out it runs exactly once after all active modify/deploy branches finish (verified: iteration advances 0→1 once even with all three branches on). Don't expect it after only the first branch.
  • propose must return program_mode ∈ {bitstream, flash}. Any other value raises propose returned invalid program_mode. (The start --program-mode has a third option debug_flash for the first pass only; propose does not.)
  • langgraph.__version__ doesn't exist on 1.2.9 — check the version via importlib.metadata.version("langgraph") if needed (smoke_test asserts >= 0.2.39).

Troubleshooting

Symptom Fix
--resume-json value shows up without quotes / split on spaces You used PowerShell. Drive via the Bash tool (single-quoted JSON).
UnicodeEncodeError: 'gbk' ... Don't use bare conda run; use the env python.exe directly (the driver reconfigures stdout to UTF-8).
{"status":"error","error":"Real mode requires pyserial"} --real needs pyserial: "$PY" -m pip install pyserial. Or drop --real for a mock run.
SerialConfigError: Missing serial sections [...] Create ~/zynq_imx6_flow.conf from zynq_imx6_flow.example.conf (relay ports may come from ~/vivado_mcp_usb.conf).
import failed ... Run /langgraph-vivado-install The langgraph env is missing/incomplete → run /langgraph-vivado-install.
propose returned invalid program_mode The propose resume used something other than bitstream/flash.
resume seems to start over You passed a different --thread-id than start. Use the same one.
Want to see the graph visually Optional: langgraph dev via the project's langgraph.json opens Studio — not required to run.