博客统计信息

51cto推荐博客
用户名:tywali
文章数:109
评论数:257
访问量:223275
无忧币:1240
博客积分:2376
博客等级:6
注册日期:2008-05-31

我的技术圈(0)

更多>>
基于OHCI的USB主机 —— 中断处理程序
2010-01-08 16:55:06
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://lancelot.blog.51cto.com/393579/261181
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队列处理完毕的时候会跳出来告诉我说队列执行完毕了,可是找了半天也没有找到,只好采用这个笨方法了。

本文出自 “rainman” 博客,请务必保留此出处http://lancelot.blog.51cto.com/393579/261181

分享至
更多
一键收藏,随时查看,分享好友!
wuyuanfeng66
1人
了这篇文章
类别:嵌入式开发技术圈()┆阅读()┆评论() ┆ 推送到技术圈返回首页

文章评论

 <<   1   2   3   >>   页数 ( 1/3 )  
2010-01-19 09:48:13
我想问下,你写这个USB代码,OHCI的手册你前前后后看了多少次了啊?
博主回复:
2010-01-21 10:31:33
所有的代码包括最后的业务应用层代码写完,花了3个月,其中前2个月都是跟OHCI在搏斗,基本上天天都在看。

2010-01-21 22:30:18
博主写的这套东西很有参考价值,要是能整理一下,搞个目录之类的,显示出连贯性,就更好了
博主回复:
2010-01-22 14:49:06
嗯,你的这个建议很好。

本来我写的是Word文档,大概100多页,目录标题一应俱全,可是贴在这里就没了,等我把这个系列文章全部贴完后再搞个目录吧。

2010-01-25 15:34:04
博主可以试试用live writer来发表看看会不会保留目录等信息,live writer的使用方法详见本文http://51ctoblog.blog.51cto.com/26414/95155
博主回复:
2010-01-25 18:02:19
谢谢,我现在基本上都使用LiveWriter来发表文章的,不过没有注意目录的问题。

 <<   1   2   3   >>   页数 ( 1/3 )  

发表评论            

【技术门诊】专家解析:软考重点难点及应试技巧
昵  称:
登录  快速注册
验证码:

请点击后输入验证码博客过2级,无需填写验证码

内  容: