![](https://csdnimg.cn/release/download_crawler_static/86176990/bg9.jpg)
对 SL811 总线式的读写函数太简单,这里不提了。那是我们这种解决方案下最底层的
函数。关键是 usb.c 中的 usbXfer ()和 ep0Xfer ()这两个函数。
2.4.3usbXfer()函数
借助分析这个函数的实现可以了解 USB 的传输模型及差错处理。
分析一下它的输入参数。
int usbXfer (BYTE usbaddr, // USB 设备地址 0-127
BYTE endpoint, // 端点的地址 0-15 ,对于 U 盘无非就是 0,1,2
BYTE pid, // 数据包 token 类型,包括 setup,pid_IN,pid_OUT
BYTE iso, // 是否使用等时传输,对于 U盘,该项恒否
WORD wPayload,// 本数据包的最大包长,又称净荷。
WORD wLen , // 待发送或接收的数据的实际长度
BYTE *buffer // 待发送的数据的缓冲首址,或者将要接收数据的缓冲首址
)
首先要了解 pid。Setup 型的 pid 只出现在控制传输阶段, 即 usb设备复位配置阶段。 Pid_IN
和 pid_OUT 可能出现在控制传输阶段和此后的 Bulk 传输阶段。 顾名思义, pid_IN 表示 Host
打算通过这次 usbXfer ,从 U 盘读进来 wLen 长度的数据, 放入 buffer 中。Pid_OUT 表示 Host
打算向 U 盘控制器发送 wLen 长度的数据或者写入 U 盘 wLen 长度的数据, 这些数据已经在
buffer 准备好。
其次是要理清 wPayload 和 wLen 的关系。 wPayload 传递过来的是该端点的最大包长,
在前面枚举中分析那 32 字节的配置描述符时应该已经记录了下来。在 USB1.1 的规范里只
能是 8,16,32,64 这四个值其中之一,实际上我根据 SL811 的打印只见过 8 字节和 64 字
节 payload 的 U 盘,而且那些 8 字节 U 盘只是端点 0 是 8 字节,BULK 端点也是 64 字节的。
应该目前来说多数 U 盘都是 64 字节的( 1.1 的范围内)。
言归正传,由于 USB 设备的端点有最大包长的限制, SL811 启动一次数据传输时必须
保证不超过这一限制,因此,在往 SL811 的 0x02 地址发送数据长度前,应作一判断,取
wPayload 和 wLen 之中的较小者。 C 代码为:
xferLen = (BYTE)((wLen>=wPayload) ? wPayload:wLen);
当 wLen < payload 的时候,一帧数据只需要 SL811 启动一次传输就能完成。
当 wLen > payload 的时候,一帧数据就需要 SL811 启动多次传输才能完成。
接着让我们根据代码来分析 usbXfer ()函数的流程。建议对照着附件中 usb.c 的代码
来看。代码的图在前,分析在后,下同。