scan_chain 命令读 IDCODE ——
该命令在 OpenOCD 0.12 中并不存在(实测报 invalid command name)。
本文给的是真正能用的方法。
| 能力 | 能否做到 | 说明 |
|---|---|---|
| 读 IDCODE | ✅ 核心功能 | 无损、秒级、可全检。识破型号不符的假料 |
| 自动识别型号 | ✅ 可以 | UrJTAG 自带器件数据库,能直接报出型号名 |
| 读 Device DNA | ✅ Xilinx 独有 | 每颗芯片唯一的 57 位 ID,用于溯源与批次核查 |
| 边界扫描(测引脚) | ⚠ 需 BSDL 文件 | 能测 I/O 开路/短路,需从原厂下载对应 BSDL |
| 验证内部逻辑功能 | ❌ 做不到 | JTAG 通 ≠ 芯片好用 |
| 测 BGA 封装 | ❌ 需专用座 | 测试座 2~5 万/型号,本方案解决不了 |
TQFP LQFP QFP PLCC SOP DIP QFN(QFN 需座)EPM240T100 EPM570T100 EPM1270T144、
MAX V 5M570ZT100、老 Cyclone EP1C6Q240 EP4CE6E22;
Xilinx CPLD XC9572XL-10TQ100、Spartan-3 XC3S50-4VQ100。| 物料 | 规格 / 型号 | 参考价 | 备注 |
|---|---|---|---|
| FT2232H 模块 | CJMCU-2232H / 通用 FT2232H 模块 | 30~60 元 | 核心件。也可用 FTDI 官方 Mini Module(约 100~150 元,更稳) |
| 杜邦线 / 排线 | 母对母 10cm,6~8 根 | 5 元 | 越短越好,长了容易通信失败 |
| 测试夹 / 探针 | SOIC 夹、鳄鱼夹、飞针 | 20~50 元 | 用于夹住引脚,比焊接方便 |
| 转接座(可选) | TQFP100 / TQFP144 测试座 | 200~1500 元 | 要全检就买,最便宜的几百元 |
| Altera 10-pin 头(可选) | 2×5 1.27mm | 5 元 | 做成标准线,插板子方便 |
| 万用表 | — | 已有 | 接线前必须测通断和电压 |
只需要 4 根信号线 + 地。这是最关键的一步,接错了什么都读不出来。
Altera 通用的 10-pin(2×5,1.27mm) 定义如下(做成线后插板子最方便):
| 脚 | 信号 | 脚 | 信号 |
|---|---|---|---|
| 1 | TCK | 2 | GND |
| 3 | TDO | 4 | VCC (3.3V) |
| 5 | TMS | 6 | NC |
| 7 | NC | 8 | NC |
| 9 | TDI | 10 | GND |
Xilinx 的 14-pin(2×7,2.0mm)定义请以官方手册为准(各系列略有差异),
查询关键词:Xilinx JTAG 14-pin pinout / UG908。
自制时建议先直连飞线验证,成功后再考虑做线缆。
# Ubuntu / Debian 一条命令装齐 sudo apt update sudo apt install -y urjtag openocd xc3sprog # 验证 jtag --version # UrJTAG 的二进制叫 jtag,不叫 urjtag openocd --version
jtag,不是你 apt 装的包名 urjtag。
这点很多教程写错。
zadig.akeo.ie),
选择 FT2232H 的 Interface A,驱动选 WinUSB,点 Install。urjtag.org 或 sourceforge 下载 Windows 版,解压到
C:\urjtag,把该目录加进 PATH。# 方法一:临时加 udev 规则(推荐) sudo tee /etc/udev/rules.d/99-ftdi.rules >/dev/null <<'EOF' SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6010", MODE="0666", GROUP="plugdev" EOF sudo udevadm control --reload-rules sudo udevadm trigger # 重新插拔模块,然后把当前用户加入 plugdev sudo usermod -aG plugdev $USER # 方法二:临时用 sudo(仅测试用) sudo jtag
0403:6010(FT2232H)。若你的模块是 FT2232D 则是 0403:6010 也常见,
用 lsusb 确认实际 ID 后再改上面规则。
UrJTAG 自带器件数据库,读出 IDCODE 后能直接告诉你型号名—— 这正是回收场景最需要的能力。
$ jtag UrJTAG 0.10 #2007 jtag> cable FT2232 FT2232 driver: vid=0x0403 pid=0x6010 jtag> frequency 1000000 (设 1MHz,先低速求稳,稳定后再往上调) jtag> detect (探测链上的器件) jtag> idcode IR length: 10 Chain length: 1 Device Id: 0000 0010 0000 1010 0001 0000 1101 1101 (0x020A10DD) Manufacturer: Altera Part: EPM240 Stepping: /1 jtag> quit
cable FT2232 → frequency 1000000 → idcode。# 把命令用管道喂进去,适合脚本化批量检测 printf 'cable FT2232\nfrequency 1000000\nidcode\nquit\n' | jtag # 只提取 IDCODE 行 printf 'cable FT2232\nfrequency 1000000\nidcode\nquit\n' | jtag 2>/dev/null | grep -i 'Device Id'
| 命令 | 作用 |
|---|---|
| idcode | 读链上所有器件的 IDCODE —— 最常用 |
| detect | 探测链上器件 |
| discovery | 用过 BSDL 自动发现链上的未知器件 |
| bsdl | 管理 BSDL 文件(做边界扫描用) |
| frequency | 设 JTAG 时钟频率 |
| scan | 读 BSR,显示自上次扫描的变化 |
| instruction | 切换/声明指令 |
| addpart | 手动添加器件(数据库没有时) |
| part | 切换当前活动器件(多器件链) |
OpenOCD 自带一批现成的器件脚本,实测包含下面这些(关键!):
| 脚本 | 对应器件 | 对回收的价值 |
|---|---|---|
| cpld/altera-epm240.cfg | Altera MAX II EPM240 | 小封装 CPLD,正是推荐的重点 |
| cpld/altera-5m570z-cpld.cfg | Altera MAX V 5M570Z | 小封装 CPLD |
| cpld/xilinx-xc7.cfg | Xilinx 7 系列 | 需配测试座 |
| cpld/xilinx-xc6s.cfg | Xilinx Spartan-6 | 需配测试座 |
| cpld/xilinx-xcr3256.cfg | Xilinx CoolRunner | 部分小封装 |
| fpga/xilinx-dna.cfg | Xilinx Device DNA | ★ 读唯一芯片 ID,见第七节 |
| fpga/altera-10m50.cfg | Altera MAX 10 | — |
| fpga/altera-ep3c10.cfg | Altera Cyclone III | 老器件,可能有小封装 |
以 EPM240 为例(脚本里内置了正确的 IDCODE,读到不符会告警):
# 先写一个接口配置:diy-ft2232h.cfg adapter driver ftdi ftdi vid_pid 0x0403 0x6010 ftdi channel 0 # 下面的 0x0008/0x000b 是 ADBUS0-3 做 TCK/TDI/TDO/TMS 的标准取值 # 格式:ftdi layout_init <初始电平> <方向位掩码, 1=输出> ftdi layout_init 0x0008 0x000b adapter speed 1000
# 连接并读链信息 openocd -f diy-ft2232h.cfg \ -f /usr/share/openocd/scripts/cpld/altera-epm240.cfg \ -c "init; shutdown" # 期望输出(关键行): Info : JTAG tap: epm240.tap tap/device found: 0x020a10dd (mfg: 0x06e (Altera), part: 0x20a1, ver: 0x0)
scan_chain 这个命令(0.12 实测不存在)。
它的做法是:你在配置里声明期望的 IDCODE,init 时它读回实际值并对比。tap/device found: 0x........Warn : expected id 0x........, got 0x........
—— 这条警告里的 got 值就是实际 IDCODE,照样能用来核对型号。
31 28 27 12 11 1 0 ┌────────┬──────────────────────────────┬───────────────┬────┐ │ Version│ Part Number │ Manufacturer │ 1 │ └────────┴──────────────────────────────┴───────────────┴────┘ 4 位 16 位 11 位 固定 1 例:0x020A10DD Version = 0x0 Part Number = 0x020A1 → MAX II 系列 Manufacturer = 0x06E → Altera 末位 = 1 (固定,可用来快速判断读取是否有效)
IDCODE = (PartNumber << 12) | (Manufacturer << 1) | 1 厂商 ID:Xilinx = 0x049 Altera = 0x06E 验证:EPM240 的 PartNumber = 0x020A1 (0x020A1 << 12) | (0x06E << 1) | 1 = 0x020A10DD ✓ 与 OpenOCD 官方脚本 altera-epm240.cfg 里写死的期望值完全一致
下面这些是从 UrJTAG 官方器件数据库 + OpenOCD 官方脚本中提取并换算验证的真实值, 可以直接拿来比对:
| 型号 | 厂商 | 封装 | IDCODE | 编程器可测 |
|---|---|---|---|---|
| EPM240 | Altera | TQFP100 等 | 0x020A10DD | ✅ 小封装 |
| EPM570 | Altera | TQFP100 等 | 0x020A40DD * | ✅ 小封装 |
| EPM3064A | Altera | PLCC/TQFP | 0x070640DD | ✅ 小封装 |
| EPM7128AE | Altera | PLCC/TQFP | 0x071280DD | ✅ 小封装 |
| EP1C6Q240 | Altera | PQFP240 | 0x020820DD | ✅ 小封装 |
| EP1C12 | Altera | Q240 / F324 | 0x020830DD | 视封装 |
| EP1C20F400 | Altera | FBGA400 | 0x020840DD | BGA,需座 |
| EP2C8 | Altera | Q208 / F256 | 0x020B20DD | 视封装 |
| XC9536XL | Xilinx | VQ44 / PC44 | 0x09602093 | ✅ 小封装 |
| XC95108 | Xilinx | PLCC/TQFP | 0x09506093 | ✅ 小封装 |
| XC3S50 | Xilinx | VQ100 / TQ144 | 0x0140D093 | ✅ 小封装 |
| XCR3128XL | Xilinx | VQ100 | 0x04889093 | ✅ 小封装 |
* EPM570 的值按 MAX II 系列规律推算(OpenOCD 脚本对 MAX II 声明了
0x020A10DD ~ 0x020A60DD 六段)。测得实际值后以实测为准。
其余各行均由数据库位段 (PartNumber << 12) | (Mfg << 1) | 1 换算得出,公式已用 EPM240 验证。
| 读出结果 | 说明 | 结论 |
|---|---|---|
| 与丝印型号一致 | 器件自报型号正确 | 通过初筛(但还不能断定是真品) |
| 与丝印型号不符 | 如丝印 XC9572 读出 EPM240 | 铁定是改标/错料,直接退货 |
| 全 0 或全 1 | 读不到有效 IDCODE | 可能:JTAG 被禁用 / 熔丝烧断 / 器件已损坏 / 接线错误 |
#!/bin/bash # jtag-scan.sh —— 批量读 IDCODE 并记入台账 OUT="jtag-log-$(date +%Y%m%d).csv" echo "时间,IDCODE,原始输出" > "$OUT" while true; do read -p "换一颗料,回车检测(q 退出):" k [ "$k" = "q" ] && break ID=$(printf 'cable FT2232\nfrequency 1000000\nidcode\nquit\n' \ | jtag 2>/dev/null | grep -i 'Device Id' | head -1) [ -z "$ID" ] && ID="读取失败" echo "$(date +%H:%M:%S),$ID" | tee -a "$OUT" done echo "记录已存:$OUT"
OpenOCD 自带脚本 fpga/xilinx-dna.cfg(实测存在),支持 Spartan-6 与 Series-7:
# xilinx-dna.cfg 内部实现(供理解,不用自己写) # Spartan6 → DNA 读地址 0x30 # Series7 → DNA 读地址 0x17 # 流程:ISC_ENABLE → 读 DNA 寄存器 → ISC_DISABLE # 实际使用(以 7 系列为例) openocd -f diy-ft2232h.cfg \ -f /usr/share/openocd/scripts/fpga/xilinx-dna.cfg \ -c "init" \ -c "xc7_get_dna xc7.tap" \ -c "shutdown" # 输出示例 DNA = 0000000000000000000000000000000000000000000000000000000 (0x0000000000000000)
cpld/xilinx-xc7.cfg),
且 BGA 封装同样需要测试座。边界扫描能测 I/O 引脚的开路 / 短路 / 固定电平,需要从原厂下载对应的 BSDL 文件。
| 厂商 | BSDL 下载 | 查询关键词 |
|---|---|---|
| Xilinx / AMD | 官网下载页,按型号搜 BSDL | Xilinx BSDL download <型号> |
| Altera / Intel | 官网 Download Center | Altera BSDL <型号> |
# UrJTAG 里挂载 BSDL jtag> cable FT2232 jtag> detect jtag> bsdl load /path/to/epm240.bsd # 载入 BSDL jtag> bsdl dump # 查看引脚定义 jtag> part 0 jtag> bsdl test # 跑边界扫描 jtag> scan # 显示引脚状态
实测可安装,依赖 libftdi1。专为 Xilinx 器件设计,能读写配置并校验。
# 列出它认识的线缆 xc3sprog -c # 基本用法 xc3sprog -c <cable> [options] <filespec> # filespec 格式:filename:action:offset:style:length # action: w=写+校验 W=自动擦除写+校验 v=校验 r/R=读 # style : BIT | BIN | BPI | MCS | IHEX | HEX # 例:校验一颗器件的配置 xc3sprog -c ft2232 design.bit:v # 例:读出配置到文件 xc3sprog -c ft2232 dump.bin:r
| 现象 | 可能原因 | 怎么查 |
|---|---|---|
cable FT2232 报无设备 |
权限 / 驱动 / USB ID 不符 | lsusb | grep 0403 看有没有认到;Linux 查 udev 规则;Windows 查 Zadig 是否换了 WinUSB |
| 读到的 IDCODE 全是 0 或全 1 | TDI/TDO 接反、没共地、目标未供电 | 万用表量通断;先把 TDI/TDO 对调试一次 |
detect 找不到器件 |
频率太高 / 线太长 / 器件没上电 | 把频率降到 100kHz 或更低;缩短杜邦线;确认 VREF 有电压 |
| 时好时坏、偶尔成功 | 接触不良 / 线太长 / 无屏蔽 | 换短线;用夹子替代手按;降频 |
| 读到 IDCODE 但型号不符 | 可能真的是改标料 | 换一颗同型号再测——若都"不符"且一致,可能是你的丝印判断错了;若各不相同,才是假料 |
| 链上有多个器件,结果混乱 | 多器件 JTAG 链 | 用 part N 逐个切换;或把其他器件 nTRST 拉低 |
UrJTAG 报 Unknown part |
数据库里没有这个型号 | 用 addpart 手动加;或看 IDCODE 自行比对厂商手册 |
检测一定要留记录,这是出报告的原始数据。
| 日期 | 型号(丝印) | 封装 | IDCODE | 读出型号 | 结论 | 备注 |
|---|---|---|---|---|---|---|
| 2026-09-30 | EPM570T100C5N | TQFP100 | 0x020A40DD | EPM570 | 一致 | 批次 A |
| 2026-09-30 | EPM240T100C5N | TQFP100 | 0x020A10DD | EPM240 | 一致 | — |
| 2026-09-30 | XC9536XL-10VQ44C | VQFP44 | 0x09602093 | XC9536XL | 一致 | — |
| 2026-09-30 | 丝印 EPM570 | TQFP100 | 0x020A10DD | EPM240 | 不符 | 退货 |
上表 IDCODE 为示例格式,实际值请以你测到的为准。