本质是 Linux 内核驱动抢占 USB 设备 的经典冲突。


🔌 1. 你的下载器是什么?

你的下载器使用了 FTDI FT2232 芯片(lsusb 显示 ID 0403:6010)。这颗芯片很强大,支持多种模式:

  • 串口模式(VCP):模拟成两个普通的串口(/dev/ttyUSB0/dev/ttyUSB1),可以像操作串口一样操作它。
  • MPSSE 模式:一种高级模式,可以通过 USB 直接控制 JTAG、SPI、I2C 等协议。

高云(以及很多 FPGA 厂商)的下载器,使用的是 MPSSE 模式,通过 libusb 库直接与芯片通信,不需要 它被模拟成串口设备。


🧠 2. 内核的 ftdi_sio 驱动是什么?

Linux 内核里有一个叫 ftdi_sio 的驱动程序,它的作用是:

  • 当你插入一个 FTDI 芯片的 USB 设备时,它会自动识别并绑定到这个设备。
  • 然后把它注册成标准的 TTY 串口设备(/dev/ttyUSBx),让你可以用 minicomscreen 等工具直接操作。

问题就在这里ftdi_sio 会在设备插入时抢先占用这个 USB 接口。一旦被占用,libusb 就无法再通过原始 USB 协议去控制它了。

你可以把它想象成:

  • 你的下载器是一块空地
  • ftdi_sio 是一个施工队,看到空地就抢先立了一块牌子:“这里归我管,要进来必须走我的大门(/dev/ttyUSBx)”。
  • 但 Gowin Programmer 想直接翻墙进去(用 libusb 直接发 USB 包),结果发现大门被施工队锁了,进不去。

🛠️ 3. sudo modprobe -r ftdi_sio 做了什么?

  • modprobe 是 Linux 用来加载/卸载内核模块的命令。
  • -r 表示 remove(卸载)。

sudo modprobe -r ftdi_sio 的作用就是:ftdi_sio 这个驱动程序从当前运行的内核中彻底踢出去

一旦这个驱动被卸载:

  • 它之前绑定的 FTDI 设备被释放
  • USB 设备变回“无驱动”状态。
  • libusb 就可以顺利接管,Gowin Programmer 就能正常通信了。

⏳ 4. 为什么半年前可以,现在不行了?

可能性有几个:

  1. 内核更新了:Linux 内核版本升级后,ftdi_sio 的自动绑定策略可能变了,或者加载时机更早了。
  2. 以前没触发加载ftdi_sio 不是开机就加载的,它是在你第一次插入 FTDI 设备时才被自动加载。半年前你插入下载器时,可能 ftdi_sio 还没有被加载到内存里(因为之前没插过其他 FTDI 设备)。但这次,可能你之前已经插过 Arduino 或其他 USB 串口设备,导致 ftdi_sio 已经在内存里了,所以下载器一插上就被它抢占了。
  3. Gowin IDE 版本变了:新版本的 Programmer 可能对设备枚举的逻辑更严格了,以前能容忍被占用的情况,现在直接报错。

⚠️ 5. 这个操作的副作用是什么?

  • ftdi_sio 被卸载后,所有 FTDI 芯片的串口功能都会暂时失效。也就是说,如果你同时插了一个基于 FTDI 的 Arduino 或 USB 转串口模块,它会暂时无法使用(/dev/ttyUSBx 会消失)。
  • 重启电脑,或者重新插入 FTDI 设备(有时会自动重新加载),或者手动执行 sudo modprobe ftdi_sio,就可以恢复。

💡 6. 有没有更优雅的长期解决方案?

有的,可以配置 udev 规则,让系统根据设备的不同用途,自动选择加载或不加载 ftdi_sio。但比较复杂,而且配置不好可能影响其他设备。对于普通用户来说,用 modprobe -r + NOPASSWD 配置已经是最实用、最干净的折中方案了。


📌 总结一句话

ftdi_sio 是 Linux 内核里负责把 FTDI 芯片变成串口的驱动,它抢占了你的下载器,导致 Gowin Programmer 无法直接控制它。modprobe -r 就是把它踢走,把设备的控制权还给 Gowin Programmer。