原创
我对usb--IN、OUT事务的软件角度理解(gliethttp)
2009-3-6 16:17
3255
14
14
分类:
通信
我对usb- - IN、OUT事务的软件角度理解( gliethttp) 文章来源: http: //gliethttp.cublog.cn[转载请声明出处] 当设置地址的setup包发送完之后 usb host主机会继续产生一个IN事务, 进而进入这里, 将setup包中设置的地址值, 配置到usb从设备上- - pdiusbd12 对于PDIUSBD12来说, 当为OUT事务数据包时, 只有包数据接收完毕之后, 才会触发PDIUSBD12的中断, 当为IN事务时, 一旦host发出IN事务的PID令牌值, PDIUSBD12会立即中断, mcu此时, 把需要发送的数据送到USB总线即可. 如果此次操作是OUT事务操作, 那么当数据全部传输完毕之后, host主机会再产生一个IN事务操作, 从机必须配合这个IN事务操作发送一个空数据包( 实际51测试slave可以不用回发0字节的空数据包;但在at91rm9200下当没有待发的数据时,当出现IN事务时,at91rm9200固件驱动会发送0字节包来响应该IN事务) 如果此次操作是IN事务操作, 那么当数据全部传输完毕之后, host主机会再产生一个OUT事务操作, 从机必须配合这个OUT事务操作返回正确ACK( ACK已经由usb控制器硬件自动完成) 所以从这里看, IN事务也好, OUT事务也好, 他们都是host主机以逻辑为出发点"乱搞" 出来的, [ gliethttp] 对于不负责任的从机, 可能端点0, 1, 2之类一旦发生数据中断, 它就发数据, 它不管当前发的数据是为IN事务服务的, 还是为OUT事务服务的, 而对于负责任的从机, 它会完全按照host提出来的IN、OUT事务的逻辑, 配合IN、OUT事务, 发送相应事务下的相应数据. 举一个例子: host下发一个数据, 所以需要产生OUT事务, 当host发送完成之后, host自己知道已经发完了, [ gliethttp] 但host比较bt, 他还想让slave做一个确认, 让slave报告一个空数据包, 他才解恨, slave怎么报告呢, slave不能主动传数据给host, 因为usb主从模式的原因, 一切数据的流动都是由host单方面主动提出发送、读取, slave只是被动的响应, 就像前面的OUT事务一样 host打算OUT数据时, 绝不会事先知会一下slave, 有了就发, 比较粗鲁, 大手大脚, 当OUT事务完成之后, host又强迫slave上发一个空数据包给host, 完全不顾及slave的感受[ gliethttp] 因为slave不能有脾气, 如果slave有了脾气, 不去理会host的IN事务, host以强硬的姿态让slave上发一个空数据包, slave就是不发, 那没办法, slave你是真的不想混了, host会不带商量的把你踢出去- - windows提示: "非法usb设备" , 所以slave为了能糊口, 在windows的一亩三分地混口饭吃, 那就只能顺着该死的host的规则来行事了[ gliethttp] , 所以IN事务也好和OUT事务, 以及setup事务, 这些都是给这样一个过程起的一个代号, 毕竟我们要和其他人交流, 总不能说, "就是那个东西,数据发出去等着回答的那个东西,我觉得它有问题" , 那交流起来多麻烦, 要是有个这个定义之后, 大家就可以这么说, "我对IN事务不理解,我对OUT事务理解了" , 简洁明了. 以上是我对usb- - IN、OUT事务的理解.
我对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个设备描述符, 可以有多个配置描述符, 每个配置描述符可以有多个接口描述符, 每个接口描述符可以管理多个端点.
文章评论(0条评论)
登录后参与讨论