ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

FT2232H USB转JTAG调试器硬件连接与引脚映射实战

FT2232H USB转JTAG调试器硬件连接与引脚映射实战 1. 为什么是FT2232HMPSSE到底解决了什么问题做FPGA或者嵌入式开发的人迟早要跟JTAG调试器打交道。以前我图省事直接买成品下载器Digilent的JTAG-HS3、Xilinx原厂的Platform Cable USB II东西是好但价格摆在那而且一旦项目里需要定制接口、特殊电平、或者想把JTAG和调试串口合到一个USB口上成品方案就变得很僵硬。后来我接触到FT2232H这颗芯片算是把这条弯路彻底走通了。FT2232H是FTDI家的双通道USB 2.0 Hi-Speed转串行芯片最有价值的地方在于它内部集成了MPSSE引擎也就是Multi-Protocol Synchronous Serial Engine。这玩意儿可以在不写固件、不折腾USB协议的前提下通过上位机库直接产生JTAG、SPI、I2C这些同步串行时序。换句话说一颗FT2232H加几个电阻电容就能做成一个USB转JTAG调试器而且成本比成品方案低一个数量级。稍微对比一下就明白它的位置了方案成本灵活性上手难度适合场景成品Xilinx下载器高低接口固定低实验室通用调试ST-Link/J-Link中中有专有协议中ARM调试为主FT2232H自研方案很低高双通道可复用中量产工装、定制板卡、嵌入式集成所以这篇文章我就用一次完整的实战记录把FT2232H的USB转JTAG硬件连接和引脚映射讲透。全程不需要写一行FPGA逻辑也不需要碰USB底层驱动跟着步骤走就能在5分钟内把链路打通。2. 5分钟硬件连接实操从裸片到JTAG链路2.1 第一步先认清FT2232H的最小系统FT2232H虽然功能多但硬件上其实很好伺候。核心就几件事供电、USB连接、EEPROM、电平引脚。我以最常见的FT2232H Mini Module或者自己画板为例最小系统长这样VCC和VCCIO接3.3V注意FT2232H的VCCIO决定了IO输出的电平这是很多新手踩坑的地方。VCCIO接3.3VADBUS和BDBUS输出就是3.3V接5V就是5V。USB DP/DM接USB座子走线尽量等长线不要太细USB 2.0 Hi-Speed对走线阻抗有要求但不算苛刻45欧姆差分阻抗尽量靠拢。EEPROM接93LC46B这是配置芯片用来存储VID、PID、序列号、通道模式这些参数。不接EEPROM芯片也能工作但每次上电都是默认配置没法改引脚映射也没法改设备名。时钟方面FT2232H内置12MHz晶振电路接一个12MHz无源晶振加两个15pF负载电容就行不需要外部有源晶振。我最初画板子的时候忽略了VCCIO和VCC的去耦结果JTAG时序在10MHz以下还能跑一旦提到20MHz以上就出错。后来在VCCIO旁边加了10uF和0.1uF的组合去耦电容问题才消失。这颗芯片对电源纹波是有要求的别省这几个电容。2.2 第二步照着这张表接JTAG引脚FTDI官方在AN_135文档里给出了FT2232H用作JTAG时的推荐引脚映射这是经过验证的你完全可以直接照抄省得自己去想映射关系。默认情况下通道A作为JTAG接口通道B可以作为UART或者SPI/I2C备用通道A引脚信号名方向对应JTAG标准说明ADBUS0TCK输出TCKJTAG时钟由MPSSE产生ADBUS1TDI输出TDI数据输入到目标芯片ADBUS2TDO输入TDO从目标芯片读回数据ADBUS3TMS输出TMS状态机切换信号ADBUS4TRST可选输出TRST测试复位低有效可选ADBUS5可选GPIO双向-可以留给复位控制这张表就是整个引脚映射的核心。实际连接的时候把ADBUS0、ADBUS1、ADBUS3接到目标板的TCK、TDI、TMS把ADBUS2接到目标板的TDO四条线就够跑标准JTAG了。TRST和SRST看情况如果你的目标板JTAG链上需要复位控制再把ADBUS4接出去。很多开发板的JTAG排针不是标准的2.54mm间距可能是2.0mm也可能是0.5mm FPC座子转接的时候别直接插先确认间距。我吃过这个亏买来的转接板插不进板子上的排针白等了两天快递。2.3 第三步电平匹配这件事千万别偷懒FT2232H的IO电平由VCCIO决定默认3.3V。你的目标板如果也是3.3V JTAG接口那直接连就行了。但现实情况往往是目标板是1.8V的内核逻辑JTAG引脚也做在1.8V电平域里这时候就需要电平转换。最简单的做法是给FT2232H的VCCIO接到目标板对应的电平上。比如目标板IO是1.8V那就把VCCIO也接1.8V。但FT2232H供电必须大于2.97V才能保证内部稳压器正常工作所以VCC和VCCIO要分开处理VCC接3.3VVCCIO单独接目标板的电平域。如果你的目标板电平是5V的直接连会出问题因为FT2232H的IO耐压最高也就5.5V但长时间工作在5V逻辑下发热严重而且输出高电平如果达不到目标板的VIH阈值JTAG时序会不稳定。稳妥的做法是加一个TXB0108或者SN74LVC8T245这类电平转换芯片把TCK、TDI、TMS、TDO全部过一遍。速率不用担心这些转换芯片跑到几十MHz完全没问题。注意共地是必须的。USB转JTAG调试器和目标板之间如果不共地轻则时序乱跳重则烧毁IO。我见过不止一次有人拿着USB供电的开发板和单独供电的目标板不共地就直接插JTAG结果TDO引脚冒烟。2.4 第四步EEPROM配置一次到位硬件连好之后还需要给FT2232H配置EEPROM让它在系统里以JTAG设备的方式出现。这里强烈推荐用FTDI官方的FT_PROG工具图形界面操作几分钟搞定。我通常在FT_PROG里做的配置如下USB VID/PID保持默认0x0403/0x6010这个VID是FTDI的没必要改改了之后上位机库还要跟着改。通道A设置为JTAG mode通道B设置为UART mode。USB String Descriptor改成自己习惯的名字比如CUSTOM JTAG Debugger方便在设备管理器里识别。如果是产品化打开Bus Powered模式并设置合适的电流值。写完EEPROM后重新插拔USB在设备管理器里看到设备名变成了你设置的名字说明配置生效了。到了这一步硬件上的准备就算完成了。3. MPSSE底层配置与JTAG时序实现3.1 MPSSE的工作原理用大白话理解MPSSE本质上是一个可编程的同步串行引擎你通过USB向它发送命令它根据命令产生时钟和数据信号。它跟CPU用GPIO模拟JTAG不同MPSSE内部是有硬件FIFO的时序由硬件生成所以能做到很高频率且稳定。你可以把MPSSE想象成一个翻译官上位机通过USB把我要产生一个JTAG的TMS序列翻译成MPSSE能识别的命令字节MPSSE再根据命令去拉高拉低TCK和TMS。整个过程中USB通信是异步的但JTAG时序是同步产生的所以时序不会因为USB调度抖动。这里有个概念要搞清楚MPSSE不关心你到底在跑JTAG还是SPI还是I2C它只是按照命令里的时钟边沿和数据位去操作引脚。所谓USB转JTAG实际上是上位机库比如libftdi、pyftdi、FTD2XX帮你实现了JTAG状态机的逻辑再转换成MPSSE命令。3.2 驱动库选哪个FTD2XX、libftdi还是pyftdi实际开发中选驱动库取决于你的场景我在不同项目里用过三种各有优缺点方式优点缺点适用场景FTD2XX官方库稳定、厂家维护闭源、Windows/Linux各一套产品级工具libftdi开源库开源、跨平台需要自己掌握更多细节Linux工装pyftdi纯Python、上手快、自带JtagController性能上限略低原型验证、脚本自动化对于快速验证硬件连接我强烈推荐pyftdi。它内置了JtagController类几行代码就能扫描JTAG链上的设备IDCODE不用你自己去实现JTAG状态机。from pyftdi.jtag import JtagManager, JtagError # 打开FT2232H通道A并初始化JTAG mgr JtagManager() mgr.configure(ftdi://ftdi:2232h/1, frequency10e6) jtag mgr.jtag # 扫描链上的设备IDCODE这个操作会自动走完整的JTAG状态机 for device in jtag.devices: print(Found device IDCODE: 0x%08X % device.idcode) jtag.close()第一次跑这段代码如果能看到目标芯片的IDCODE打印出来说明你的硬件连接和引脚映射完全正确。这是我最推荐做的第一步验证比盲目加载比特流要安全得多。如果是做量产测试工具我会用C和FTD2XX写因为FTD2XX提供了更底层的控制可以在不经过中间层的情况下直接操作MPSSE信号性能最好。但开发工作量也大需要自己维护JTAG状态机。3.3 时钟分频和TCK频率怎么算FT2232H内部的时钟架构是这样的12MHz晶振经过PLL倍频到480MHz再分频得到60MHz的系统时钟最后MPSSE命令里的分频系数divisor决定实际的TCK频率。计算公式如下TCK频率 60MHz / (divisor 1) / 2注意是除以二因为JTAG时钟需要保证一个完整的高电平和低电平周期。如果你设置divisor为2那么TCK就是60/(21)/210MHz。实际应用中TCK频率不是越高越好。频率越高对信号完整性的要求越高线长了之后反射和串扰带来的时序问题就越明显。我一般遵循这样的选择原则调试阶段用1MHz到10MHz稳定性优先。量产烧录用10MHz到30MHz速度优先。30MHz以上对线缆长度、接口连接器品质都非常敏感不建议在普通杜邦线下尝试。另外目标芯片的JTAG引脚本身也有最大频率限制有些低功耗MCU的TCK最高只能到10MHz超过这个值设备就会不稳定。稳妥的做法是先翻一下目标芯片手册里的JTAG时序参数再决定分频系数。3.4 从MPSSE命令到JTAG时序如果你想知道MPSSE到底是怎么产生JTAG时序的可以看下面这个简单的例子。MPSSE命令字节0x4A表示带写TDI和读TDO的时钟数据字节后面的长度参数和下一位数据字节会决定具体的信号行为。# 用pyftdi直接发送原始MPSSE命令 from pyftdi.mpsse import MpsseController ctrl MpsseController() ctrl.configure(ftdi://ftdi:2232h/1) # 配置GPIO方向ADBUS0-TCK输出, ADBUS1-TDI输出, ADBUS2-TDO输入, ADBUS3-TMS输出 ctrl.set_gpio_direction(0b00001011, 0b00001011) # 发送MPSSE命令序列 ctrl.write([0x4A, 0x00, 0x00, 0x55]) # 移位8位数据0x55写TDI读TDO data ctrl.read(1) print(Returned: 0x%02X % data[0])不要被command字节吓到实际项目里直接操作命令字节的场景很少大部分时候是库函数帮你封装好了。但理解这些命令能帮你排查问题比如当TDO读回全1或者全0的时候你知道是引脚方向配置错了还是时钟没产生。4. 与Vivado协同连接硬件时生成固化文件4.1 从JTAG在线调试到固化文件生成用FT2232H自制的下载器在Vivado里的体验和官方下载器基本一致因为Vivado的硬件管理器通过FTD2XX的D2XX Direct驱动识别设备不认是不是原厂硬件。这点我在多个版本的Vivado上验证过从2018.3到2023.2都没问题。JTAG连接正常之后你可以在Vivado Hardware Manager里看到目标设备这时候在线加载比特流只是第一步。真正让我第一次觉得自制下载器有用的场景是需要在连接硬件的情况下生成固化文件。很多新手在这个地方会卡住在Vivado里点击Generate Bitstream生成了bit文件但断电之后程序就丢了因为bit文件只是加载到FPGA内部SRAM里掉电消失。想要固化到外部FLASH需要生成MCS或者BIN文件然后通过JTAG写到FLASH里。4.2 连接硬件状态下生成并烧录固化文件以Xilinx 7系列FPGA为例完整流程是这样第一步确定FLASH型号。不同板子上的SPI FLASH型号不同常见的有W25Q64、W25Q128、S25FL128S等。打开Vivado Hardware Manager在目标设备上右键选择Add Configuration Memory Device。第二步在弹出的对话框里选择你的FLASH型号。选择时要对应到具体的器件型号和封装Vivado会根据型号自动匹配配置位宽和指令集。如果型号不在列表里选一个同厂商同系列参数最接近的试试但不一定100%兼容最好用官方支持的型号。第三步点击OK之后Vivado会提示你加载比特流文件。这时候选择Generate Bitstream输出的bit文件然后勾选Program Configuration Memory Device选项Vivado会先通过JTAG加载一个临时bitstream来初始化FPGA然后再通过SPI接口写入FLASH。在这个过程里FT2232H就扮演了两个角色先是JTAG调试器然后通过JTAG链路间接操作目标板的SPI FLASH。整个链路是PC - USB - FT2232H - JTAG - FPGA - SPI FLASH每一步都要配合好任何一环出问题都会导致烧录失败。4.3 三招解决Vivado烧录固化的常见报错烧录固化的过程中我踩过的坑和解决办法分享给大家。第一出现Configuration memory device programming failed这类报错大概率是FLASH型号选错了。我有一次把W25Q64选成了W25Q128烧录到一半报错排查了半天才发现是型号不匹配。还有一个可能是FLASH的WP写保护引脚被拉低了检查一下电路板上的WP引脚应该接上拉到3.3V。第二出现MCS file generation failed通常是生成MCS文件时没有指定正确的FLASH容量和配置模式。在Vivado的Settings - Bitstream里把Config rate设成33MHz如果你的FLASH支持的话把Configuration Memory Part改成实际型号再生成一次。第三烧录过程中CRC错误。如果你用的是SPI x4模式但FLASH不支持或者硬件上只连接了x1模式就会出现CRC错误。这时候把SPI总线宽度改成1-bit重新生成固件。注意固化文件烧录完成后记得断掉JTAG并重新上电观察FPGA是否能从FLASH正常启动。不要带着JTAG线在线观察启动状态因为JTAG的连接状态本身会影响FPGA的配置优先级。5. 扩展玩法FT2232H第二通道做RTC调试和I2C监控5.1 一枚芯片同时干两件事的硬件连接FT2232H最让我喜欢的地方就是双通道通道A跑JTAG的同时通道B还能干别的活。实际项目里板子上常常既有FPGA又有RTC芯片这时候通道B完全可以当作第二套调试口来用。RTC芯片用I2C接口的最常见比如PCF8563、DS3231、RX8025这些。FT2232H的MPSSE模式原生支持I2C硬件上只需要把通道B的BDBUS0接SDABDBUS1接SCL再加两个上拉电阻就可以了。引脚对应关系如下通道B引脚信号说明BDBUS0SDA数据线需要上拉电阻到VCCIOBDBUS1SCL时钟线需要上拉电阻到VCCIOI2C上拉电阻的选择有讲究。FT2232H的IO驱动能力不算强上拉电阻太小会让信号边沿变缓通常4.7k欧在100kHz下没问题如果要跑400kHz可以换成2.2k欧。我习惯在PCB上预留多个焊盘位方便后期调整。5.2 用Python脚本读RTC时间接好线之后用pyftdi的I2cController类读RTC时间非常方便。以PCF8563为例这个芯片的时间寄存器从0x02开始连续6个字节分别存储秒、分、时、日、星期、月。from pyftdi.i2c import I2cController i2c I2cController() i2c.configure(ftdi://ftdi:2232h/2) # 注意这里的2表示通道B # PCF8563的I2C地址是0x517位地址 slave i2c.get_port(0x51) slave.write([0x02]) # 把内部地址指针设到秒寄存器 data slave.read(6) # PCF8563的时间寄存器是BCD编码 def bcd2bin(val): return (val 0x0F) ((val 4) * 10) seconds bcd2bin(data[0] 0x7F) minutes bcd2bin(data[1] 0x7F) hours bcd2bin(data[2] 0x3F) print(Time: %02d:%02d:%02d % (hours, minutes, seconds))这个脚本在调试RTC驱动的时候特别好用。你可以先用它确认硬件I2C通路是好的再去调FPGA或MCU里的软件驱动出了问题能快速定位是硬件还是软件。5.3 第二通道还能干的事除了I2C第二通道还可以配置成UART、SPI、GPIO。我最常用的组合是通道A做JTAG通道B做调试UART这样一根USB线连到板子上既能在Vivado里烧FPGA又能打开串口终端看调试打印效率直接翻倍。硬件上只需要把通道B的BDBUS0配置为TXDBDBUS1配置为RXD接到目标板的串口交叉线上。在FT_PROG里把通道B模式设置成UART然后设备管理器里就会出现一个新的COM口波特率115200或者921600都行看你的场景。如果你想用第二通道做GPIO控制测试比如复位信号、使能信号、LED指示pyftdi也支持GpioController可以直接在线控制引脚高低电平。这个功能在板卡调试初期特别有用可以在上电前先验证信号通路。6. 常见问题排查与避坑实录6.1 一张表解决90%的硬件问题我把自己用FT2232H做USB转JTAG过程中遇到的高频问题整理成下面的速查表按照这个顺序排查大多数问题都能解决现象可能原因检查方法解决方案电脑识别不到USB设备USB线不支持数据传输换一根已知好的USB线使用带屏蔽的高质量线缆设备识别为未知设备EEPROM配置损坏看设备管理器错误码用FT_PROG重新烧录EEPROMJTAG扫描不到设备共地没接万用表量GND连通性连接调试器和目标板GNDJTAG扫描不到设备TDO不匹配逻辑分析仪看TDO波形检查ADBUS2是否接对IDCODE读出来全是0TCK频率过高降到1MHz试试提高分频系数降低TCKIDCODE读出来全是1TDO悬空测TDO引脚电平检查排针接触和焊接时序不稳定偶发失败电源去耦不足看VCCIO纹波加去耦电容减小噪声高温下不稳定目标板电平过高测IO引脚电压加电平转换电路6.2 三个最容易忽略的细节第一个是EEPROM里的Bus Powered和Self Powered设置。如果你用的是USB供电的调试器一定要在EEPROM里设置成Bus Powered并填一个合理的电流值。我见过有人默认使用Self Powered配置结果USB口识别设备后很快掉线就是因为供电模式没配对。第二个是复位控制的接线。很多FPGA板子的JTAG接口里还包含了PROG_B或者SRST信号这些信号一般通过JTAG的VREF或者单独引脚引出。如果你的FT2232H没有接这些信号也能正常工作但某些操作会受限比如在线升级固件时无法自动复位FPGA。这种情况下可以手动给板子断电重启。第三个是信号线长度。JTAG信号在10MHz以下时杜邦线长度控制在20cm以内一般没问题。如果超过这个长度建议使用屏蔽线或者差分方式传输。我做量产测试工装的时候把JTAG线压在带屏蔽的FFC排线里信号质量比杜邦线稳定很多。6.3 为什么TDO读回来的数据总是不对这是新手最容易迷惑的地方。硬件连接都检查过了IDCODE能读出来但读写FLASH的时候数据就是不对。排查几次之后发现问题往往出在TCK的上升沿采样时序上。JTAG标准规定TDO在TCK下降沿输出TDI在TCK上升沿采样这由JTAG状态机和芯片内部逻辑自动完成。MPSSE在驱动引脚的时候会保证这个时序但如果TCK频率太高或者信号线上容性负载过重导致边沿变缓就可能超过芯片规定的建立保持时间。解决思路有两个方向一是降低TCK频率二是优化信号质量。我一般优先降低频率因为这最省事。只有当频率必须保持在较高水平时才会去调整PCB走线、加串阻、改善信号完整性。串阻的值一般在22欧到47欧之间靠近信号源端放置。6.4 自制下载器能被Vivado识别吗可以但有个前提条件你的FT2232H的VID/PID必须是FTDI官方的默认值或者你把VID/PID改成了Vivado认识的设备ID。Vivado通过FTD2XX驱动枚举设备它识别的不一定是VID/PID准确说它枚举所有连接到电脑上的FTDI设备然后逐个尝试是否是JTAG设备。在实际使用中我发现Vivado的硬件管理器在识别FT2232H设备时主要看它能不能跟设备的MPSSE接口通信成功。所以只要你的硬件连接正确EEPROM配置没损坏一般都能被正常识别。如果识别不到先确认FTD2XX驱动是否安装成功可以到设备管理器里看有没有带FTDI标志的串行设备。另外Vivado本身对FT2232H的支持也是标准的官方文档UG908里有关于Digilent下载器的工作原理描述其实就是FT2232H的参考实现。所以我说自制下载器和官方下载器在Vivado里的体验基本一致这不是吹牛是架构上就决定的。落地到自己的项目从我第一次接触FT2232H到现在已经用它做过FPGA调试器、量产烧录工装、RTC产线测试治具、调试串口扩展卡每次把它用到一个新场景都觉得这颗芯片还有潜力没挖完。硬件连接加引脚映射这件事看起来是最基础的步骤但恰恰是决定整个项目稳定性的地基。如果你正准备在自己的板子上集成USB转JTAG功能我的建议是从一份标准参考设计开始先用FTDI的评估板跑通功能再移植到自己的PCB上别一上来就追求高集成度。引脚映射就用官方推荐的ADBUS0到ADBUS3不要擅自改动等稳定了再考虑精简电路或者改用更小封装。这个思路能帮你省下大量排查问题的时间。
返回列表