初始化代码搞定:
static vsf_err_t vsfohci_poll(void *param)
{
struct vsfohci_t *ohci = (struct vsfohci_t *)param;
uint32_t tickcnt_now;
uint32_t cmd;
switch (ohci->state)
{
case VSFOHCI_STAT_UNINIT:
memset(ohci->hcca, 0, sizeof(struct vsfohci_hcca_t));
ohci->revision = vsfohci_read_reg(ohci, OHCI_REGIDX_HcRevision);
// read RWC
ohci->control = vsfohci_read_reg(ohci, OHCI_REGIDX_HcControl);
// Disable HC interrupts
vsfohci_write_reg(host, OHCI_REGIDX_HcInterruptDisable, OHCI_INTR_MIE);
// Reset HC
vsfohci_write_reg(host, OHCI_REGIDX_HcControl, 0);
vsfohci_write_reg(host, OHCI_REGIDX_HcCommandStatus, OHCI_CMDR_HCR);
ohci->state = VSFOHCI_STAT_INITDELAY;
ohci->tickcnt = interfaces->tickclk.get_count();
ohci->state = VSFOHCI_STAT_INIT_POLLHCR;
// break; // fall through
case VSFOHCI_STAT_INIT_POLLHCR:
cmd = vsfohci_read_reg(ohci, OHCI_REGIDX_HcCommandStatus);
if (cmd & OHCI_CMDR_HCR)
{
tickcnt_now = interfaces->tickclk.get_count();
if ((tickcnt_now - ohci->tickcnt) > 30)
{
// timeout
ohci->state = VSFOHCI_STAT_UNINIT;
}
}
else
{
// reset finished
uint32_t control = vsfohci_read_reg(ohci, OHCI_REGIDX_HcControl);
vsfohci_write_reg(ohci, OHCI_REGIDX_HcControl,
(control & ~OHCI_CTRLR_HCFS_MASK) | OHCI_CTRLR_HCFS_RESET);
ohci->HcControl = OHCI_CTRLR_HCFS_RESET;
// delay 100 ms
ohci->tickcnt_orig = interfaces->tickcnt.get_count();
ohci->delayms = 100;
ohci->next_state = VSFOHCI_STAT_INIT_END;
ohci->state = VSFOHCI_STAT_POLLDELAY;
}
break;
case VSFOHCI_STAT_INIT_END:
{
uint32_t fminterval = 12000 - 1;
uint32_t mask;
vsfohci_write_reg(ohci, OHCI_REGIDX_HcControlHeadED, 0);
vsfohci_write_reg(ohci, OHCI_REGIDX_HcBulkHeadED, 0);
vsfohci_write_reg(ohci, OHCI_REGIDX_HcHCCA, ohci->hcca);
vsfohci_write_reg(ohci, OHCI_REGIDX_HcPeriodicStart,
fminterval * ohci->period_ratio / 100);
vsfohci_write_reg(ohci, OHCI_REGIDX_HcFmInterval,
((((fminterval - 210) * 6) / 7) & 7FFF) << 16);
vsfohci_write_reg(ohci, OHCI_REGIDX_HcLSThreshold, 1576);
ohci->HcControl = OHCI_CTRR_INIT | OHCI_CTRR_OPER;
vsfohci_write_reg(ohci, OHCI_REGIDX_HcControl, ohci->HcControl);
// enable and clear interrupt mask
mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
vsfohci_write_reg(ohci, OHCI_REGIDX_HcInterruptEnable, mask);
vsfohci_write_reg(ohci, OHCI_REGIDX_HcInterruptStatus, mask);
// root hub init
break;
}
case VSFOHCI_STAT_POLLDELAY:
tickcnt_now = interfaces->tickclk.get_count();
if ((tickcnt_now - ohci->tickcnt) >= ohci->delayms)
{
ohci->state = ohci->next_state;
}
break;
case VSFOHCI_STAT_OPERATIONAL:
break;
}
// put here if in poll mode, otherwise call vsfohci_irq in irq handler
vsfohci_irq(ohci);
return VSFERR_NONE;
}
简单说一下为什么评估这个不难。
1. 调试工具和分析工具都齐全,包括USB协议分析仪
2. linux里的OHCI驱动很简单,1000多行代码,当然这个是GPL的协议,我们用不了,而且基于操作系统的
3. 我摸个不少于5个各个厂家的USB协议栈,自己做过通用的USB协议栈,当然是设备端
明天上班,给公司里的人接手了。 |