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能够刷新驱动中的数据缓存)
部署:
https://github.com/SpinalHDL/SaxonSoc/tree/dev-0.3/bsp/digilent/ArtyA7SmpLinux
https://github.com/SpinalHDL/SaxonSoc/tree/dev-0.3/bsp/radiona/ulx3s/smp
用法
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))
}