基于OHCI的USB主机 —— 中断处理程序

OHCI的体系下,判断数据是否传输完毕是需要通过中断程序来判断的,当USB主机设置了HcControlHcCommandStatus寄存器开始传输数据后,AM9200 自动开始数据传输,并且定期的检查HcDoneHead寄存器的内容,并且将其转移到HCCA.DoneHead。然后产生中断,触发中断处理程序。

 

在中断处理程序中,需要检查HcInterruptStatus寄存器的内容,判断WDH位是否为1,以便确定是否有TD被处理完毕。一般来说,其余的中断状态位不用理会。当发现有TD被处理完毕,则还需要判断已经完成的TD是否是当前传输命令的最后一个TD,如果是则标志命令执行结束,上层程序可以进行后续处理。

 

/**

 * OHCI中断处理程序

 */

void AT91F_UHP_Handler(void)

{

    unsigned int status;

    unsigned char idx;

    unsigned char cc;

    //unsigned int control;

   

    //得到HcInterruptStatus寄存器的内容

    status = ohciGetIntrStatus();

    //检查WDH位,判断是否有TD传输完毕

    if ((status & OHCI_HC_INTR_WDH) != 0)

    {

       //根据当前执行的命令类型,确定TD的数量

       switch(usbCmdState.cmdType)

       {

       case USB_CMD_TYPE_BULK_WRITE:

       case USB_CMD_TYPE_BULK_READ:

           idx = 3;

           break;

          

       case USB_CMD_TYPE_CTRL_READ:

           idx = 2;

           break;

          

       case USB_CMD_TYPE_CTRL_WRITE:

           idx = 1;

           break;

          

       default:

           usbCmdState.state = USB_CMD_OVER;

           ohciClearIntrStatus();

           return ;

       }

      

       //取得当前完成的TDComplete Code

       cc = getTdCC(ohciGetHccaDoneHead());

       //判断当前完成的TD是否是命令的最后一个TD

       if (ohciGetHccaDoneHead() == usbGetLastTdAddr(idx))

       {

           usbCmdState.cmdResult = cc;

           usbCmdState.state = USB_CMD_OVER;

       }

       else

       {

           //当前TD不是最后一个TD,但是执行失败,不会继续处理TD列表,因此需要返回

           if (cc)

           {

              usbCmdState.cmdResult = cc;

              usbCmdState.state = USB_CMD_OVER;

           }

           else

              //当前TD不是最后一个TD,等待继续处理

              usbCmdState.state++;

       }

    }

    //清除HcInterruptStatus寄存器的内容,以便能够产生新的中断

    ohciClearIntrStatus();

}

 

在最初的代码中,不是通过中断来判断TD数据是否处理完毕的,而是直接调用ohciGetIntrStatus()函数并判断返回值的,但是实际调试时发现这样不能正确得到TD数据处理完毕的信息。通过对中断程序的实际调试发现,因为ED会带有多个TDAM9200在处理的时候可能是处理速度的原因,会产生1个或多个中断,因此在中断处理程序中需要判断当前结束的TD是否是当前命令的最后一个TD,这样才能确保整个ED处理完毕。

 

说实话,我不认为上面的判断ED队列执行完毕的方法是好的方法,本来我一直以为会有一个寄存器,在ED队列处理完毕的时候会跳出来告诉我说队列执行完毕了,可是找了半天也没有找到,只好采用这个笨方法了。





本文转自 tywali 51CTO博客,原文链接:http://blog.51cto.com/lancelot/261181,如需转载请自行联系原作者
上一篇:解决Word出错--一打开就反复重启的问题


下一篇:40个优秀的单页网站设计范例(下篇)