本帖最后由 Simon21ic 于 2014-12-23 01:37 编辑
我是来秀代码的逗比
OHCI是全速USB使用的主机控制器标准,这里就以各种不同的代码对比看看哪个好玩。
linux2.2:
1721 static int hc_reset (ohci_t * ohci)
1722 {
1723 int timeout = 30;
1724 int smm_timeout = 50; /* 0,5 sec */
1725
1726 if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
1727 writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
1728 dbg("USB HC TakeOver from SMM");
1729 while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
1730 wait_ms (10);
1731 if (--smm_timeout == 0) {
1732 err("USB HC TakeOver failed!");
1733 return -1;
1734 }
1735 }
1736 }
1737
1738 /* Disable HC interrupts */
1739 writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
1740
1741 dbg("USB HC reset_hc: %x ;", readl (&ohci->regs->control));
1742
1743 /* Reset USB (needed by some controllers) */
1744 writel (0, &ohci->regs->control);
1745
1746 /* HC Reset requires max 10 ms delay */
1747 writel (OHCI_HCR, &ohci->regs->cmdstatus);
1748 while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
1749 if (--timeout == 0) {
1750 err("USB HC reset timed out!");
1751 return -1;
1752 }
1753 udelay (1);
1754 }
1755 ohci->disabled = 0;
1756 return 0;
1757 }
linux是多任务操作系统,作为高帅富,可以肆无忌惮的调用wait_ms。我等DS只能羡慕妒忌恨。
当然,对于我的非阻塞状态机,这么调用是致命的,那就列一下传统状态机的实现方式:
static vsf_err_t vsfohci_init_nb(struct vsfohci_t *vsfohci)
{
uint32_t temp;
struct ohci *ohci = vsfohci->ohci;
switch (vsfohci->init_state)
{
case VSFOHCI_INITSTAT_UNINITED:
temp = readl(&ohci->regs->control);
if (temp & OHCI_CTRL_IR)
{
/* request ownership */
writel(OHCI_OCR, &ohci->regs->cmdstatus);
vsfohci->init_state = VSFOHCI_INITSTAT_POLL_OCR;
vsfohci->loops = 50;
}
else
{
vsfohci->init_state = VSFOHCI_INITSTAT_DISABLE_INT;
}
break;
case VSFOHCI_INITSTAT_POLL_OCR:
/* quiry ownership */
temp = readl(&ohci->regs->control);
if (temp & OHCI_CTRL_IR)
{
writel(OHCI_OCR, &ohci->regs->cmdstatus);
vsfohci->loops--;
if (vsfohci->loops <= 0)
{
vsfohci->init_state = VSFOHCI_INITSTAT_UNINITED;
return VSFERR_FAIL;
}
vsfohci_init_delay_nb(vsfohci, 10, VSFOHCI_INITSTAT_POLL_OCR);
}
else
{
vsfohci->init_state = VSFOHCI_INITSTAT_DISABLE_INT;
}
break;
case VSFOHCI_INITSTAT_DISABLE_INT:
/* Disable HC interrupts */
writel(OHCI_INTR_MIE, &ohci->regs->intrdisable);
/* Reset USB (needed by some controllers) */
ohci->hc_control = 0;
writel(ohci->hc_control, &ohci->regs->control);
/* HC Reset requires max 10 us delay */
writel(OHCI_HCR, &ohci->regs->cmdstatus);
temp = readl(&ohci->regs->cmdstatus);
if (temp & OHCI_HCR)
vsfohci_init_delay_nb(vsfohci, 2, VSFOHCI_INITSTAT_POLL_HCR);
else
vsfohci->init_state = VSFOHCI_INITSTAT_HC_START;
break;
case VSFOHCI_INITSTAT_POLL_HCR:
temp = readl(&ohci->regs->cmdstatus);
if (temp & OHCI_HCR)
{
vsfohci->init_state = VSFOHCI_INITSTAT_UNINITED;
return VSFERR_FAIL;
}
vsfohci->init_state = VSFOHCI_INITSTAT_HC_START;
break;
case VSFOHCI_INITSTAT_HC_START:
....
关键的延时函数:
static void vsfohci_init_delay_nb(struct vsfohci_t *vsfohci, uint32_t ms,
enum ohci_init_state next_state)
{
vsfohci->tickcnt = interfaces->tickclk.get_count();
vsfohci->delayms = ms;
vsfohci->init_next_state = next_state;
vsfohci->init_state = VSFOHCI_INITSTAT_DELAY;
}
延时只是进入一个叫VSFOHCI_INITSTAT_DELAY的状态对应的时间长度,时间到后,再进入下一状态
系统可以正常运行,也是非阻塞的,只是代码。。。。。。
下面是EDA构架的PT线程:
static vsf_err_t vsfohci_init_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)
{
vsf_err_t err;
struct vsfusbh_t *usbh = (struct vsfusbh_t *)pt->user_data;
vsfsm_pt_begin(pt);
/* init HCD timer */
usbh->hcd_timer.sm = pt->sm;
/* get resource for OHCI controller */
if (VSFERR_NONE != vsfohci_get_resource(usbh, CONFIG_SYS_USB_OHCI_REGS_BASE))
return VSFERR_FAIL;
/* request ownership */
if (VSFERR_NOT_READY == vsfohci_init_request_ownership(usbh->hcd_data))
{
do
{
/* delay 10 ms, then check OCR */
usbh->hcd_timer.interval = 10;
usbh->hcd_timer.evt = VSFSM_EVT_HCD_WAIT_OCR;
vsftimer_register(&usbh->hcd_timer);
vsfsm_pt_wfe(pt, VSFSM_EVT_HCD_WAIT_OCR);
/* timer expired, unregister it */
vsftimer_unregister(&usbh->hcd_timer);
/* check OCR */
err = vsfohci_init_check_ocr(usbh->hcd_data);
if (err < 0)
return err;
} while (err == VSFERR_NOT_READY);
}
/* disable HCD interrupt */
if (VSFERR_NOT_READY == vsfohci_init_disable_interrupt(usbh->hcd_data))
{
/* delay 2ms, then check HCR */
usbh->hcd_timer.interval = 2;
usbh->hcd_timer.evt = VSFSM_EVT_HCD_WAIT_HCR;
vsftimer_register(&usbh->hcd_timer);
vsfsm_pt_wfe(pt, VSFSM_EVT_HCD_WAIT_HCR);
/* timer expired, unregister it */
vsftimer_unregister(&usbh->hcd_timer);
/* check HCR */
err = vsfohci_init_check_hcr(usbh->hcd_data);
if (err < 0)
return err;
}
/* delay XX ms before the HCD is ready */
usbh->hcd_timer.interval = vsfohci_init_hc_start(usbh->hcd_data);
usbh->hcd_timer.evt = VSFSM_EVT_HCD_WAIT_HCD;
vsftimer_register(&usbh->hcd_timer);
vsfsm_pt_wfe(pt, VSFSM_EVT_HCD_WAIT_HCD);
/* timer expired, unregister it */
vsftimer_unregister(&usbh->hcd_timer);
vsfsm_pt_end(pt);
return VSFERR_NONE;
}
当然,这个代码还只是一个刚刚接触PT线程的人写的,还不是最终代码。
那么问题来了,这个PT线程的代码,是阻塞的吗?
|