Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15497875
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2007-09-22 18:58:34

我对PDIUSBD12、at91rm9200-usb的IN、OUT事务的硬件角度理解(gliethttp)

文章来源:http://gliethttp.cublog.cn[转载请声明出处]

<1>对于PDIUSBD12,对于OUT事务,只有当pc驱动程序把此次数据通过管道全部发送到usb设备端点
   --PDIUSBD12的0或2的数据缓冲区和ACK之后,PDIUSBD12才会产生中断,通知cpu,处理接收到的OUT事务数据,
   而不是在PDIUSBD12收到OUT令牌后就立即中断cpu,PDIUSBD12会等到OUT令牌之后的数据阶段
   (也可能需要等到ACK握手阶段完成之后[gliethttp])完成之后,才触发中断通知cpu处理PDIUSBD12接收到的
   数据缓冲区中的数据;
   对于控制端点0、端点1和端点2的IN事务,只要IN令牌一收到,PDIUSBD12就会立即触发中断,
   0xF4中断状态寄存器的bit1-控制输入端点状态位-置位,
   以示cpu这次中断由于控制端点IN令牌包的收到而发生的,
   固件驱动组织数据,之后发送给host主机.(gliethttp)
   这样就比较麻烦,因为当固件驱动处理数据的时候,PDIUSBD12将主动返回NAK给host主机,host主机收到NAK
   之后,会按固定时间间隔定时的发送IN事务令牌包,如果不将cpu的整个中断系统停掉的话,至少不把
   PDIUSBD12的第14脚INT_N连接的cpu中断禁止的话,就会以很高的频繁对cpu进行INT_N中断,
   当然也可以不使用中断,而是不停检测PDIUSBD12的第14脚INT_N是否为0.
<2>对于at91rm9200来说,只有如下几种情况才会引发中断:
   (1.RXSETUP:当前端点收到了setup令牌包触发中断
   (2.RX_DATA_BK0:当前端点收到了数据包并且已经安全放到了FIFO段0触发中断
   (3.RX_DATA_BK1:当前端点收到了数据包并且已经安全放到了FIFO段1触发中断
   (4.TXCOMP:当前端点上发的数据已经被host主机通过IN事务读取,同时PID_ACK也正常收到,触发TXCOMP中断
   (5.STALLSENT:当前端点被挂起禁用触发中断
   所以对于at91rm9200第1次收到"读取设备描述符"setup事务指令之后会引发cpu中断,在中断里边
   usbEp0.DisptachSetup = AT91F_USB_DispatchRequest;回调函数中,得知是STD_GET_DESCRIPTOR-标准获取设备描述符,
   固件驱动会立即把"设备描述符"送入控制端点的IN缓冲区,这个时候host主机可能还正在处理其他事情,没有时间来处理,
   不怕,放到IN缓冲区中的数据at91rm9200的usb控制器不会在host主机没有发送PID_IN令牌之前,就把数据主动送到总线
   上丢失掉,而是等待host主机对当前端点发送PID_IN令牌的时候,老早之前放到IN缓冲区的数据才会传输出去,
   另外的那种情况就是,host主机速度快的惊人,刚刚发送完"读取设备描述符"setup事务指令,就立即又发送了PID_IN令牌,
   这时at91rm9200的usb控制器还没有把"设备描述符"完全送到IN缓冲区,此时at91rm9200的usb控制器会自动向host主机
   发送PID_NAK,作为PID_IN的握手回应.经过几次PID_NAK并且在没有超过50ms的前提下,at91rm9200固件驱动已经把数据放
   到了IN缓冲区,并且使IN缓冲区生效,那么host定时再次发送过来的PID_IN令牌将能正常收到PID_DATA令牌下的数据了.
   这种方式比较好,在OUT事务中,固件驱动得知是否有上传数据,然后直接在OUT中断中,把上传数据送到IN数据缓冲区,
   当host正常读取IN缓冲区的数据之后,会触发IN中断,在IN中断中,固件驱动再去检查IN数据是否发送完毕,如果没有就
   继续发送下去,这就好像"钟摆小球试验",当你轻轻给它一个"外力"--OUT事物中激活IN,之后,"小球"--IN事物中断,就开始
   永远的"摆动"起来--IN事物中断,又有点类似自激震荡(gliethttp).
<3>usb通信时,每一次数据的传送都严格遵守3个阶段
      [1]令牌PID阶段
      [2]数据PID阶段
      [3]握手PID阶段

     PID域
      -----------------------
     令牌有4种:
      PID_setup令牌--PID域值0xB4,用来标示数据阶段的数据为setup事务数据
      PID_out令牌 --PID域值0x87,用来标示数据阶段的数据为out事务数据
      PID_in令牌 --PID域值0x96,用来标示数据阶段的数据为in事务数据
      PID_sof令牌 --PID域值0xA5,用来标示帧标号开始
      -----------------------
     数据阶段:
      PID_DATA0数据--PID域值0xC3,用来标示此数据为PID偶分组数据
      PID_DATA1数据--PID域值0xD2,用来标示此数据为PID奇分组数据
      -----------------------
     握手阶段有3种:
     PID_ACK --PID域值0x4B,用来标示usb接收器硬件收到无误的数据分组
     PID_NAK --PID域值0x5A,用来标示接收端不能接收数据(可能正在处理上一次接收到的数据)
     或者发送端不能发送数据(固件驱动程序正在把IN数据放到管道端点缓冲区中)
     PID_STALL --PID域值0x78,用来标示当前端点被禁用了.(gliethttp)
<4>一个usb设备只能有1个设备描述符,可以有多个配置描述符,
   每个配置描述符可以有多个接口描述符,每个接口描述符可以管理多个端点.

阅读(3293) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2008-06-19 17:02:01

"当host正常读取IN缓冲区的数据之后,会触发IN中断,在IN中断中,固件驱动再去检查IN数据是否发送完毕,如果没有就继续发送下去" 你的意思是前面的数据并不是在IN中断里上传的,后面没传完的才到IN中断里继续传?是这样的?

chinaunix网友2008-06-19 16:54:29

在OUT事务中,固件驱动得知是否有上传数据,然后直接在OUT中断中,把上传数据送到IN数据缓冲区-----------不太理解这句话,发下去的数据我如果要回到应用层去做处理下,再决定是否上传数据呢?谁知道要上传什么数据,怎么会在out中断里去激活IN,把上传数据送到IN数据缓冲区?