USB OHCI

SpinalHDL库中有USB OHCi控制器(主机)。

用几个要点总结支持的功能:

  • 它遵循 OpenHCI USB开放式主机控制接口规范 (OHCI)。

  • 它已经与上游的linux/uboot OHCI驱动兼容。(tinyUSB上也有OHCI驱动)

  • 它提供了USB主机全速和低速功能(12Mbps和1.5Mbps)

  • 在linux和uboot上测试过

  • 一个可以承载多个端口(多至16个)的控制器

  • 用于DMA访问的Bmb存储器接口

  • 用于配置的Bmb内存接口

  • 内部物理层需要一个时钟,该时钟需要为12 Mhz的倍数,至少48 Mhz

  • 控制器频率不受限制

  • 无需外部物理层

经过测试且功能正常的设备:

  • 大容量存储(ArtyA7 Linux上约为8 Mbps)

  • 键盘/鼠标

  • 音频输出

  • 集线器

限制:

  • 某些USB集线器(目前已有一个)对将低速设备连接至全速主机的模式不友好。

  • 某些现代设备无法在USB全速上运行(例如:Gbps以太网适配器)

  • 需要与CPU保持内存一致性(或者需要CPU能够刷新驱动中的数据缓存)

部署:

用法

import spinal.core._
import spinal.core.sim._
import spinal.lib.bus.bmb._
import spinal.lib.bus.bmb.sim._
import spinal.lib.bus.misc.SizeMapping
import spinal.lib.com.usb.ohci._
import spinal.lib.com.usb.phy.UsbHubLsFs.CtrlCc
import spinal.lib.com.usb.phy._

class UsbOhciTop(val p : UsbOhciParameter) extends Component {
  val ohci = UsbOhci(p, BmbParameter(
    addressWidth = 12,
    dataWidth = 32,
    sourceWidth = 0,
    contextWidth = 0,
    lengthWidth = 2
  ))

  val phyCd = ClockDomain.external("phyCd", frequency = FixedFrequency(48 MHz))
  val phy = phyCd(UsbLsFsPhy(p.portCount, sim=true))

  val phyCc = CtrlCc(p.portCount, ClockDomain.current, phyCd)
  phyCc.input <> ohci.io.phy
  phyCc.output <> phy.io.ctrl

  // propagate io signals
  val irq = ohci.io.interrupt.toIo
  val ctrl = ohci.io.ctrl.toIo
  val dma = ohci.io.dma.toIo
  val usb = phy.io.usb.toIo
  val management = phy.io.management.toIo
}

object UsbHostGen extends App {
  val p = UsbOhciParameter(
    noPowerSwitching = true,
    powerSwitchingMode = true,
    noOverCurrentProtection = true,
    powerOnToPowerGoodTime = 10,
    dataWidth = 64, //DMA data width, up to 128
    portsConfig = List.fill(4)(OhciPortParameter()) //4 Ports
  )

  SpinalVerilog(new UsbOhciTop(p))
}