Downtown Doug Brown » 修复无法使用的仿冒 Altera USB Blaster

接下来讲述的是我如何修复两个不同的有缺陷的 Altera USB Blaster 克隆设备的故事,这些设备在我购买后从未正常工作过。

我最近建了一些 用于 HDMI 输入延迟测试的 Time Sleuths。Time Sleuth 是一个简洁的小型开源项目,可让您测量电视或显示器显示图像所需的时间。它的工作方式是 Altera/Intel MAX 10 FPGA 创建一个视频信号,该信号主要是黑屏,有一些闪烁的白色方框。它将图像馈送到 TI TFP410 DVI 发送器,并寻找光电探测器上的脉冲。它测量白框闪烁和光电探测器看到它之间的时间差,并将其显示为生成的视频信号上的数字,以及一些最小/最大/平均统计数据。太酷了!如果你不喜欢焊接,你也可以购买完全组装好的。

不管怎样,在焊接好电路板后,我必须将比特流闪存到 Altera FPGA。我立即发现 官方 Altera/Intel USB Blaster JTAG 电缆售价 300 美元。我不愿意花那么多钱买一个我可能永远不会再使用的编程器,而且我注意到市面上有很多便宜的克隆产品,所以我做了一些研究并决定购买一个克隆产品。

我读到了很多关于 Terasic USB Blaster,但我认为 69 美元的价格还是有点偏高,所以我选择了更便宜的。事后看来,我完全错了。对于一款信誉良好的产品来说,69 美元的价格非常合理。Terasic 编程器本来是最好的选择,可以避免我将要描述的混乱,所以如果您正在阅读本文并试图决定购买哪种编程电缆,请记住这一点。

我选择了 Waveshare USB Blaster V2。Waveshare 的网站看起来很不错,我看到 至少有一个相当不错的推荐 在 Reddit 上。我确实注意到 亚马逊评论称它在 Linux 上运行不稳定,但我还是不顾警告买了。最坏的情况是,我可以使用 Windows。

好吧,事实证明,一星评价是正确的。我甚至会说,在描述 Linux 兼容性时,它过于乐观了。我无法用这个该死的东西正确地编程 FPGA 根本 在 Linux 中,至少使用 Quartus Programmer 或相关命令行工具。它会在编程过程的随机部分失败。擦除有时确实有效,但要求执行的操作越长,失败的可能性就越大。这很可怕,因为我开始认为我在构建我的第一个 Time Sleuth 时犯了一个错误,但后来我启动了我的 Windows 10 VM,它在第一次尝试时就完美地编程了。我已经确认它在 Windows 中始终运行良好。

我要说的是,我能够通过播放 SVF 文件让它与 OpenOCD 和 UrJTAG 一起工作,但它真的很慢,而且感觉很笨重。我想要一些与 Quartus Programmer 兼容的东西!我向 Waveshare 询问如何让它在 Linux 中工作,这是他们两天后的回答:

抱歉,我们没有在Linux PC上测试过,应该有兼容性问题。

建议在Windows PC上使用。

这时,我打开它看了看。它实际上非常漂亮。

它使用 FTDI FT245RL 和 Altera EPM3064A CPLD,以及 Nexperia 74LVC244A 缓冲器。我经常看到人们说 FTDI + CPLD USB Blaster 克隆通常比市面上非常便宜的克隆设备质量更高。这是因为 Altera 的实际 USB Blaster(无论如何是版本 1)在内部使用类似的设置。我不确定它是否与 Altera 的设计一样好,但我喜欢看到里面有 74LVC244A 缓冲器。据我所知,它被用作电平转换器以确保与不同电压的兼容性,这就是 Waveshare 能够说它支持 1.2V 至 5V 编程电压的原因。我并不确信 5V 编程电压实际上符合 74LVC244A 推荐的 1.2V 至 3.6V 电源电压范围的规格,但我离题了。

为什么这样的设备在 Windows 上可以正常工作,但在 Linux 上却不行?Altera 软件在 Windows 和 Linux 上看起来非常相似。如果他们没有使用相同的代码库,我会感到震惊。这似乎是我调查的完美对象,特别是因为我有一个硬件 USB 嗅探器。我查看了原始 USB 流量,尽管硬件嗅探器最终对此来说有点小题大做。Windows 和 Linux 之间的流量实际上看起来有很大不同。我猜 Windows 软件组装 JTAG 命令的方式略有不同,而 Windows 的某些方式使其与此设备配合得更好。

为了限制我所研究的范围,我决定只关注 Linux。由于我可以让 Linux 在擦除芯片等短暂的过程中成功或失败,所以我 使用 Wireshark 进行 usbmon 捕获 好的和坏的擦除。然后我深入研究了捕获的内容。

首先,我需要了解 USB Blaster 工作原理我对 JTAG 也不太了解, 所以我读了它。USB Blaster 的协议其实很简单。简单概括一下链接信息,主机向设备发送一堆字节。如果传输字节中的最高位是 0,则其余位包含原始状态,可直接放在各个 JTAG 引脚上,并控制状态 LED。如果最高位是 1,则底部 6 位包含长度,然后后面有那么多字节包含 8 位,这些位将通过 TDI/TCK 连续移出。所以基本上,如果您不需要像 TMS 那样摆弄其他引脚,字节模式是一种更快发送数据的优化方式。

在两种模式下,位 6 都用于告诉 USB Blaster 也从 TDO 引脚读取数据并将其发送回计算机。即使自上次以来没有读取任何数据,USB Blaster 也会每毫秒左右发出一次心跳包。这些数据包似乎总是以两个字节作为前缀:0x31 和 0x60。我注意到 Waveshare 设备有时会发送“0x31 0x00”作为前缀,但我认为这并不重要。

接下来,我阅读了上面链接的 JTAG 文档。它解释了它是如何成为状态机的,并且 TMS 引脚用于决定每次发生 TCK 循环时如何在不同状态之间跳转。它还提供了一些有用的示例,说明如何找出 JTAG 链上存在哪些设备(如果有)。我手动解码了 Wireshark USB 捕获中的 JTAG 操作。以下是发送到 Blaster 的记录数据包的示例:

0000   7e 7f 7e 7f 7e 7f 7e 7f 7e 7f 7e 7f 7c 7d 7e 7f
0010 7c d0 ff 03 b3 3f fc ff ff ff ff ff ff ff ff ff
0020 ff ff 7c 7d 7c 7d 7c 7c 7c 7c 7c 7c 7c 7c 7c 7c
0030 7c 7c 7c 7c 7c 7c 7c 7c 7c 7c 7c 7c 7c 7c 7c

以下是我收到的回复:

0000   31 60 03 03 03 03 03 03 03 03 03 03 03 03 03 03
0010 03 03 03 77 43 60 0c fc 03 b3 3f fc ff ff ff ff
0020 ff ff ff 03 03 03 03 03 03 03 03 03 03 03 03 03
0030 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03

您会注意到响应比传输多一个字节。实际上,它少一个字节,因为“31 60”前缀不算在内。它少一个字节的原因是传输的“D0”字节设置了位 7,因此它表示我们将进入 16 个字节的字节模式(低 6 位为 0x10 = 16)。该字节本身实际上不执行任何操作,因此不会导致发送响应字节。但由于其中设置了位 6,因此传输的所有 16 个字节都将具有相关响应。它们在响应中显示为“77 43 60 … ff ff ff”。

深入探讨这次传输的具体细节远远超出了本文的范围,但这里发生的事情是 Altera 软件正在读取所连接芯片的 IDCODE。在十六进制转储中很难看到,因为位不在完美的字节边界上,但 Altera CPLD 响应了芯片 ID 0x031810DD,这是 10M02SCE144 应该如何响应

我继续跟踪 USB/JTAG 跟踪,最终发现成功和失败捕获之间的数据读回有所不同。Altera 软件似乎试图进入 Shift-IR 状态,但进入该状态后我们得到的读回没有意义。

此时,我别无选择,只能怪适配器出了问题。当给定 精确的 两次输入相同。它是随机的。它似乎可能与时间有关,比如它可能正好处于设置/保持时间超出规格的边界上。

以下是示波器上显示的流量。具体来说,这是优化字节模式流量 (TCK) 的样子:

我确实注意到了其中的一些奇怪之处。脉冲频率为 6.25 MHz。这是有道理的,因为振荡器频率为 25 MHz,所以它被除以 4。我的理解是,像这样的设计,包括原始的 USB Blaster,通常都有一个 6 MHz 的 JTAG 时钟。我开始怀疑它是否稍微超频了。我认为这可以解释间歇性行为。我甚至找到了一个 2006 年的旧讨论 “kawk” 为此设置设计了一个 CPLD 比特流,将其设计稍微超频至 25 MHz,并且运行正常,但其他人报告了问题,不得不放慢速度。

这给了我一个想法。FTDI 芯片有自己的内部振荡器,因此我可以完全自由地调整 CPLD 的运行频率,而不会干扰任何 USB 电路。我手边没有任何振荡器,但我有一个可以使用的 RPi Pico。我在 MicroPython 中编写了一个简单的程序,将 GP0 设置为占空比为 50% 的 24 MHz 时钟信号:

from machine import Pin, PWM
pwm = PWM(Pin(0))
pwm.freq(24000000)
pwm.duty_u16(32768)

然后我从 Waveshare Blaster 中移除了 25 MHz 振荡器,并将一根电线焊接到 Pico 的 GP0 上(另一根电线用于接地)。

当我用万用表验证频率时,我发现 RP2040 输出的是 25 MHz 信号,尽管我要求的是 24 MHz。我很快意识到这是因为 Pico 默认时钟频率为 125 MHz,而 PWM 频率必须是该频率的整数除数。我可能可以使用 machine.freq() 更改 Pico 的频率,但继续增加分频器更简单。(125/6) = 20.83 MHz,远低于 24 MHz。

以 20.83 MHz 运行,它似乎仍然不稳定。所以我将时钟速度进一步降低到 (125/7) = 17.86 MHz。按照这个速度,它基本上可以正常工作!不过我确实看到它失败了几次,所以我认为我离可靠性越来越近了。下一个最低可能频率 (125/8) = 15.625 MHz 似乎是最佳点。它每次都能以较慢的时钟速度完美运行。成功了!

我仍在等待 Digi-Key 提供一些随机振荡器,以便彻底解决此问题。我在考虑使用 RP2040 作为替代品之前就订购了它们,因此我订购的速度为 24 MHz、20 MHz 和 12 MHz。我希望我也能订购 15 或 16 MHz 的振荡器。我非常有信心,焊接 12 MHz 振荡器将解决所有问题,之后 Waveshare USB Blaster 将在 Linux 中完美运行。当然,它会让一切变慢很多,但至少它是可靠的。

我仍然有点困惑,为什么这个问题在 Windows 中从未发生过。我猜 CPLD 设计有一个微妙的时序错误,而 Windows 版本的 Altera/Intel 软件没有发现这个错误,因为它以完全不同的方式安排 USB 数据包中的 JTAG 流量。

通常情况下,这应该是这类博客文章的结尾,但你可能已经注意到,我在开头提到我修复了两个不同的 USB Blaster 克隆。系好安全带,因为我们才刚刚开始。在 Waveshare 无法工作之后,在我弄清楚到底发生了什么之前,我买了 亚马逊上更便宜的一款,售价 9 美元

根据评论,我对此并不十分乐观。很多评论都说它根本不起作用。几位评论者说它使他们的 Windows 计算机蓝屏。尽管有这些评论,并且考虑到我为这个问题投入了多少时间,我认为看看这个廉价的克隆产品有什么问题会很有趣。我疯了吗?

昨天下午它就到了。我把它插到我的 Linux 机器上试用了一下。当然,它没用。这并不奇怪。它显示了正确的设备 ID,软件也正确识别了它,但 Quartus Programmer 一点也不喜欢它。

usb 3-2: New USB device found, idVendor=09fb, idProduct=6001, bcdDevice= 4.00
usb 3-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-2: Product: USB-Blaster
usb 3-2: Manufacturer: Altera
usb 3-2: SerialNumber: FFFFFFFF

据我根据快速的 Wireshark USB 捕获所见,除了一件事外,流量看起来很正常。它没有响应任何数据。根本没有响应数据包,即使应该出现的周期性空闲“31 60”数据包也没有。

然后我在 Windows 中尝试了一下,并立即复制了 蓝屏死机 其他评论者提到的问题。它很快就给我一个蓝屏,错误检查是 PFN_LIST_损坏。我甚至没有足够的时间打开 Quartus Programmer 软件。快速谷歌搜索后发现 我不是唯一一个在使用廉价 Altera USB Blaster 克隆产品时遇到这个问题的人其他人的解决方案通常涉及尝试自定义 Windows 驱动程序,但我真的不想这么做。无论如何,我并不真正关心 Windows 支持。它在 Linux 上不起作用,而这才是我唯一关心的。

是的,就像大多数评论所说的那样,这个克隆似乎完全没用。这很有趣,因为我也看到网上很多人说廉价的克隆效果很好。我想肯定有不同的版本,其中一些比其他版本效果更好。我决定打开这个,看看里面是什么样子:

只有一个芯片,在图片中无法识别。这是一个 WCH CH552G微控制器。这是几年前在互联网上流传的那些极其便宜的微控制器之一。它是一款 8 位 8051 MCU,具有相当多的巧妙小功能。例如,它具有无晶振 USB 支持。截至撰写本文时,LCSC 有几块库存,每块 0.62 美元。就其功能而言还不错。但是,我认为这个电路板设计非常简单,是一个很好的例子,说明您如何物有所值。据我所知,它是硬连线的 3.3V 操作。每个引脚上都有串联电阻,所以我不知道这是否有助于避免在连接低压设备时造成损坏。

我四处搜索,看看是否有其他人在 USB Blaster 克隆产品中遇到过这些芯片。我发现许多其他廉价克隆产品都有 STM32 或 PIC 微控制器。我猜市场上充斥着不同的版本。一些说他们的产品运行良好的人一定是买了不同的型号,或者至少是不同的固件。

我发现其中有几处提到使用了 CH552G。有一件有趣的事情是 几个月前 Hackaday 上有人开发了一个 (闭源),以及 另一个 5 年前的项目,采用开源固件,基于 Blinkinlabs 的 CH55x SDCC SDK 端口

这似乎正合我意!一个新的想法/挑战浮现在我的脑海中。我能否将 5 年前的开源固件编译并运行在我刚买的这个无法使用的 CH552G USB Blaster 克隆版上?它能在 Linux 中正常工作并避免 Windows 蓝屏死机吗?Time Sleuth 的运行电压为 3.3V,因此试用它是完全安全的。

当然,我无法抗拒接受这样的挑战。所以昨晚,我开始了。还有什么比这更好的周五晚上呢?第一个任务是使用万用表上的连续性模式确定引脚映射。电路板非常简单,MCU 非常小,所以我很快就得到了我需要的整个引脚排列:

  • 引脚 1 – P3.2 – TMS
  • 引脚 2 – P1.4 – NCS
  • 引脚 3 – P1.5 – TDI
  • 引脚 4 – P1.6 – TDO
  • 引脚 5 – P1.7 – TCK
  • 引脚 6 – ?
  • 引脚 7 – ?
  • 引脚 8 – ?
  • 引脚 9 – P1.1 – 活动 LED (ACT)
  • 引脚 10 – P3.3 – ASDO
  • 引脚 11 – P3.4 – NCE
  • 引脚 12 – USB D+
  • 引脚 13 – USB D-
  • 引脚 14 – GND
  • 引脚 15 – VCC
  • 引脚 16 – V33

接下来,我启动并运行了 CH55x SDK。 SDK 的 GitHub 项目 非常棒。没过多久,我就准备尝试一个程序来让活动 LED 闪烁。我只需修改“闪烁”示例以使用 P1.1 而不是 P1.7 并构建它即可。

有这么多 很棒的教程 关于 如何使用这些芯片,所以弄清楚如何编程并不是什么问题。我安装了 ch55xtool。这些芯片很酷,因为它们有一个 USB 引导程序,如果在启动时将引脚保持在高位,它会将其置于编程模式。您不需要特殊的编程器或任何东西。数据表说您需要在 5V 下运行才能刷新它们,但到目前为止我发现刷新在 3.3V 下也可以正常工作。他们确实说每个芯片只能获得大约 200 个刷新周期,因此您不能疯狂地尝试刷新。哦,好吧,它们很便宜,所以没那么重要。

为了将其强制放入引导加载程序,我只需将一根电线夹在 3V3 和 D+ 引脚之间(这两个引脚恰好位于接头上),将其插入,然后快速拔出电线,以避免短路时间过长,同时允许 USB 通信开始。电阻器可能更安全。

然后它在 Linux 中显示为不同的 USB 设备,所以我知道我做对了:

usb 3-1: new full-speed USB device number 69 using xhci_hcd
usb 3-1: New USB device found, idVendor=4348, idProduct=55e0, bcdDevice= 2.50
usb 3-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0

此时,我脑子里闪过一个念头:一旦我继续前行,就没有回头路了。我会删除此设备上的原厂固件,我唯一的希望就是让这个开源固件正常工作。不过我不在乎。该设备使用原厂固件是没用的,所以我没什么可失去的。这是我运行的刷新芯片的命令:

ch55xtool -v -f blink.bin

刷新成功了,但我的闪烁测试固件根本不起作用!LED 上什么都没发生。我检查了其他引脚,没有任何生命迹象。我非常恼火。我真的以为我已经做好了这方面的功课。我尝试了一些其他刷新实用程序——甚至是供应商在 Windows 中的 WCHISPTool。什么都没用。我尝试将芯片上的所有配置设置重置为默认值,以防其中一个设置被搞砸了,但似乎没有什么可以修复它。我开始担心我所做的所有逆向工程工作都是徒劳的。

大约一个小时后,我恢复了理智,意识到我应该开始进一步修改示例代码,以了解它失败的原因。我注意到在 main() 的开头调用了 CfgFsys()。我尝试将其注释掉,突然间 LED 开始闪烁!(以错误的速率,但没关系)。当我意识到 CfgFsys() 正在写入 CLOCK_CFG 寄存器时,进一步阅读数据表就发现了问题。SDK 在 examples/Makefile.include 中默认 FREQ_SYS 为 24 MHz,但当芯片在 3.3V 下运行时,它最多只能达到 16 MHz。我只需在 Makefile 中将 FREQ_SYS 覆盖为 16000000 或更低即可。一旦我这样做了,闪烁的 LED 演示就成功了,我一切就绪了!

下一步是编译开源 CH55x-USB-Blaster 固件。最简单的方法是将其放入 SDK 的示例文件夹中作为另一个示例项目。它甚至在自己的 Makefile 中包含了 ../Makefile.include,所以我认为这是 CH55x-USB-Blaster 开发人员想要集成它的方式。我 将 FREQ_SYS 覆盖添加到其 Makefile 中我还修改了引脚映射。他们大部分都是正确的,但我不得不 删除引导加载程序进入按钮 并移动几个引脚。我还注意到代码在传输数据包时发送的前缀是“01 60”,而不是“03 60”,所以我继续 将其改为与原始 USB Blaster 匹配

完成这些操作后,我尝试将其插入……但什么也没发生。好吧,几乎没有任何反应。我的电脑检测到插入了设备,但之后什么也没发生。在 Wireshark 中,似乎正在发送对设备描述符的请求,但没有任何响应。

usb 3-1: new full-speed USB device number 88 using xhci_hcd

查看代码中的 USB IRQ 处理程序,我对处理帧起始 (SOF) 中断的方式产生了怀疑。看起来 SOF 中断没有被正确清除。我只是完全禁用了 SOF 中断以进行测试。它似乎并不特别重要;它只是递增一个计数器,后来用于决定不时发送一个空闲的“03 60”数据包。

一旦我禁用它,我重新刷新的 USB Blaster 克隆就恢复了活力!

usb 3-1: new full-speed USB device number 92 using xhci_hcd
usb 3-1: New USB device found, idVendor=09fb, idProduct=6001, bcdDevice= 4.00
usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-1: Product: USB-Blaster
usb 3-1: Manufacturer: Altera
usb 3-1: SerialNumber: C0BFA6D7

令人惊讶的是,在这种状态下,它在 Linux 中运行得非常好。我成功修复了价值 9 美元的廉价 USB Blaster,现在它可以正常工作并刷新我的 Time Sleuth!我太兴奋了!

然后我将其插入 Windows 以查看是否已修复 Windows 兼容性,结果它立即出现蓝屏。它与之前出现的 PFN_LIST_CORRUPT 错误完全相同。

这到底是怎么回事?但是现在它可以在 Linux 上运行了!Windows 怎么会不高兴呢?

我认为这里发生的情况是,如果您的设备假装是 FTDI 芯片,但无法完美模拟它,当官方 FTDI 驱动程序没有看到它所期望的东西时,就会发生奇怪的事情。我将把这留给读者来判断这是 FTDI 的意外还是故意。无论是否意外,我认为如果设备没有正确响应,驱动程序可能会导致系统崩溃,这非常糟糕。无论如何,我记得我已经禁用了 SOF 中断,这是发送空“03 60”数据包频率逻辑的一部分。我查看了一些其他代码示例,了解类似的 USB 控制器如何处理 SOF 中断, 相应地调整了固件

实施此更改后,SOF 中断似乎现在可以按预期工作。当我嗅探 Linux 中的流量时,我注意到编程器正在使用时周期性出现空的“03 60”数据包,并且插入时 Windows 不再崩溃。我成功地在 Linux 和 Windows 中从 Quartus 编程器刷新我的 Time Sleuths,没有任何问题。

在我让它完全工作后,我意识到活动 LED 灯反了。它大部分时间都亮着,忙碌时熄灭。我只需要 反转代码中的 LED。这是一个快速修复。我注意到的唯一另一件奇怪的事情是 Time Sleuth 将电源反馈到廉价的 USB Blaster,因此我尝试同时将它们插入电源以确保安全。我认为我无法通过软件修复此问题。

这是我的 CH55x-USB-Blaster 固件的 GitHub 分支,以及 发布二进制文件,您可以将其刷入到您的设备 如果你也犯了和我一样的错误,买了一个完全没用的 USB Blaster 克隆版。请记住以下几点:电路非常简单,似乎只设计用于 3.3V 编程。只有当你的 USB Blaster 的引脚排列与我的相同时,它才会起作用。如果你尝试这个固件,导致你没用的 USB Blaster 变砖,我不承担任何责任。不过,如果它能解决这个问题,我会获得很多赞誉!赞誉也归于 GitHub 上的 VladimirDuan 介绍了 CH55x USB Blaster 固件的原始实现, 也 Blinkinlabs 出色的 SDK 移植。更不用说 圣地亚哥会议中心!看到如此多的开源项目帮助实现这样的解决方案真是太棒了。

一晚上的工作成果还不错,对吧?我只花了几个小时就把一块价值 9 美元的亚马逊垃圾变成了一个可以正常使用的 USB Blaster 克隆版。我对自己很满意!我不想过分吹嘘自己,但这些垃圾设备完全无法使用,却以完全无法使用的形式出售,这似乎有点荒谬,而我只花了一个晚上就拼凑了一些开源固件来修复它。他们甚至会测试这些东西吗?

我对我研究的第一台设备 Waveshare USB Blaster 的研究也感到满意。我非常确定,只要我焊接一个较慢的振荡器,它也会开始完美地工作,尽管速度比它可能的速度慢。弄清楚如何制作一个新的比特流加载到它中,使其能够以完整的 25 MHz 原始时钟速率运行,这真的很酷。不过,在这样的项目上,我可能需要一些帮助。

我希望这些信息对某些人有用!

Leave a Reply

Your email address will not be published. Required fields are marked *

近期新闻​

编辑精选​