前面我们完成了工具的开发,打造了瑞士军刀级别的工具,现在就到了宝刀出鞘,是骡子是马拉出来溜溜的时候了,到了工具发挥价值的时候了。我们就用其来测试下高速批量传输的速率。当然我们之前的工具在高速传输处理时还有待优化的地方,之前是提交一笔传输然后等待传输处理完,然后继续下一笔传输。这样两次传输之间有间隔无法达到最大速率所以我们先优化下这部分。然后我们再进行实测。
原来的处理方式是,启动时提交一次传输,传输处理完时再提交下一次传输,这样两次传输之间有时间间隔,效率达不到最高。
可以优化为,启动时提交多笔传输,这样第一笔传输完成时此时后续还有传输正在进行,此时又可以提交后续传输,这样传输不间断,达到最大效率。
代码修改如下
其中s_rx_tn变量在启动传输时设置为大于1, 可以设置大点保证能按照上述示意图流式处理,启动之后设置为1这样每CB一次再提交一次。
/* 接收处理 */
if((s_rx_itf_idx != -1) && (s_rx_busy == 0))
{
int address;
int type;
int mps;
uint32_t sendlen;
struct libusb_transfer* transfer;
for(int n=0; n
{
uint8_t* buffer = malloc(s_rx_size);
if(buffer != NULL)
{
if(0 == usbdev_get_endpoint_info(s_rx_itf_idx, s_rx_ep_idx, &address, &type, &mps))
{
if((type & 0x03) == 1)
{
transfer = libusb_alloc_transfer((s_rx_size+mps-1)/mps);
}
else
{
transfer = libusb_alloc_transfer(0);
}
if(transfer != NULL)
{
switch(type & 0x03)
{
case 0:
//epstr = epstr + "CTRL";
break;
case 1:
libusb_fill_iso_transfer(transfer,s_opened_handle,address,buffer,s_rx_size,(s_rx_size+mps-1)/mps,&rx_cb,0,100);
libusb_set_iso_packet_lengths(transfer,mps);
break;
case 2:
libusb_fill_bulk_transfer(transfer,s_opened_handle,address,buffer,s_rx_size,&rx_cb,0,10);
break;
case 3:
libusb_fill_interrupt_transfer(transfer,s_opened_handle,address,buffer,s_rx_size,&rx_cb,0,10);
break;
}
s_rx_busy = 1;
if(libusb_submit_transfer(transfer) < 0)
{
s_rx_busy = 0;
libusb_free_transfer(transfer);
free(buffer);
}
else
{
}
}
else
{
free(buffer);
}
}
else
{
free(buffer);
}
}
}
s_rx_tn = 1; /* 开始之后每次只提交一笔 */
}
USB2.0规格书中对于理论最大速度计算如下
按照最大包长512字节,一个微帧最大发送13包,则最大速率是
(1mS/125uS)*13*512B/mS, 即8*13*512B/mS,即53248000B/S,即52000KB/S≈50MB/S。
但是以上是理想状态,实际上总线上还有协议消耗,一个微帧发不到13包,我们下面就实测下某款设备。
我这里是之前实现的一款winusb设备,IN端点的bInterval设置为0表示从不NAK,这样HOST会以最大速率发送IN请求数据。
我这里驱动实现,使用的是Scatter/Gather DMA模式,依赖硬件DMA一次可以传输大量数据。
usbd_winusb_send,即一把挂载描述符链表一次发送1,843,218字节数据。
实测一个微帧125uS,一个微帧发了11包,包最大512字节,
所以最大速率是(1mS/125uS)*11*512B/mS, 即8*11*512B/mS,即45056000B/S,即44000KB/S≈43MB/S。
使用我们的工具测试:
如下接收到文件,因为编辑框处理太慢无法处理这么快的数据流,传输大小设置大一点,否则两次传输之间会有间隔。
用二进制工具打开我们接收到的文件,正好是一次发送数据1843218的倍数,且内容正确。
我们来看
持续发送0.040937900
空闲时间0.0327448968
所以平均速率是0.040937900/(0.040937900+0.0327448968)*43M = 23.8M
和我们工具实测 22082916B=21M差不多,因为我们是从按动按钮开始计算时间,再次按按钮结束时间,所以时间要比实际长一点,测的速率要小一点。
以上可以看到由于两次发送之间有空闲,所以该设备没有达到最大效率,提高效率的方法是一次交给硬件DMA发送更多的数据,2是修改驱动实现环形描述符链表,不间断发送(这里有时间后续再分享一篇文章)。
以上利用我们之前自己设计的工具实现了速率的测试,自己设计的工具就是非常趁手,真香!所以磨刀不误砍柴工,多积累一些自己的组件,工具,轮子是嵌入式开发增长经验提高效率的一种手段。