最近一直在学习USB,总算是稍微有点懂了。现在自己写的PC端USB驱动程序和应用程序终于可以成功实现STM32的BULK /INT传输和有数 据/无数据传输控制请求等功能(STM32固件的程序我是用STM32 USB开发工具包中的UART范例进行的修改)。应用程序与STM32通讯测试基 本没啥问题了,就是有关传输速度的问题一直比较困惑。 STM32的USB接口是USB1.1的全速接口,进行BULK传输的时候,端点最 大的包大小按照USB规范是64个字节,并且按照USB1.1FULLSPEED的规范,USB数据的传输是基于令牌的,也就是说假如设备打算要向主机发 送数据,必须先由主机发送一个IN的令牌,设备收到令牌后,紧接着在其第二阶段送出要发送的数据,如此完成一个数据的IN操作。 而规范上 定义令牌发送的间隔是1毫秒,这样就意味着如果按照BULK传输最大64字节的规定,则最大传输速率是64字节*(1/1毫秒)=64K字节/秒。不过规 范上也说到一个令牌后面可以跟多个USB传输事务,也就是个令牌(1帧)最大可以跟15个64字节的数据,1毫秒的间隔,这样可以达到64字 节*15*1000 = 960K字节/秒的理论最大传输速度。 现在假如我有一个4KB的数据要传输,现在我是分成多个64字节的请求进 行传输的,在BUS HOUND5上看到传输的速度大约只有40KB/S不到,显然这个速度很不理想。我的问题是怎样才能在传输的时候在一帧内连续传输 15个事务使STM32传输速度最快?在STM32的USB开发包中具体如何实现?有没有这样的程序范例能供学习下,还请大家不吝赐教,谢谢! ---------------------------------------------------------------------------------------------- 要想真正提高USB的传输速度,必须在驱动中连续传输64字节的 也就是说,应用程序必须将较大的数据包交给驱动程序,由驱动程序把这个较大的数据包拆成多个64字节的数据包并发送出去;同理接收时,USB驱动程序必须先把多个64字节的数据包组合成较大的数据包,再交给应用程序处理。 关键的因素是应用程序与驱动程序的数据交换和调用转换是非常耗时的! ---------------------------------------------------------------------------------------------- STM32进行USB传输时提高传输速度-建议 首先,使用BULK传输来保证无差错的传输,这点应该没有疑义-已经做了。 其次,建议把STM32的USB模拟成 Mass Storage的设备,从而自己可以不用写驱动程序,而借用M$的现成驱动。 第三,STM32的Firmware端可以借用ST提供的参考代码-U盘的那个代码,从而可以模拟出来U盘。 第四,PC端的应用程序可以自己编程,也可以使用ST提供的动态链接库(记得是storeacc.dll),该链接库在ST-LINK/ST-LINK2的驱动程序里面可以找到。假如PC端的应用程序自己编程也不难,可以用DeviceIOControl来做。 目标是:速度接近USB Full speed的U盘的速度,800kB估计可以做到。 ---------------------------------------------------------------------------------------------- 简易示波器暂停了,主要是听取大家的建议,要把STM32的USB功能用起来,所以就开始学USB啦,等把USB搞明白之后再继续了。USB搞起来的难度可真不小,又是驱动程序的编写要学,又是固件编程,到现在也没搞明白。好在编程是件快乐的事情,哈哈~ 刚才又实验了下,现在驱动程序方面的速度瓶颈已经解决了。主要还是这个PipeMaxTransferSize的关系,这个值越大速度越快。晚上注意到这个值很多USB设备的驱动程序都是设的很大的,连HID设备都设成4096,我的一个U盘也是4096,KEIL的ULINK设置成65535,几乎所有USB设备驱动的端点0都是设成65535。晚上测试了下,这个值不会影响数据传输,这个最大值不管怎么设实际USB设备管道每次接收的数据该64字节还是64字节,应该是WINDOWS核心驱动层收到来自USB驱动的IRP后会自动拆包成与设备固件定义的大小(64字节)进行发送的。 做了下速度对比 pipemaxtranfer:64---33KB/S pipemaxtranfer:512--265KB/S pipemaxtranfer:1024--349KB/S pipemaxtranfer:4096--457KB/S pipemaxtranfer:65535--506KB/S 又试着在STM32的固件上做了个改动 EP3_OUT的回调函数把缓冲拷贝的部分先注释掉,如下: /******************************************************************************* * Function Name : EP3_IN_Callback * Description : * Input : None. * Output : None. * Return : None. *******************************************************************************/ void EP3_OUT_Callback(void) { //count_out = GetEPRxCount(ENDP3); //PMAToUserBufferCopy(buffer_out, ENDP3_RXADDR, count_out); SetEPRxValid(ENDP3); }这2句先注释掉,使得STM32的EP3收到数据后不拷贝,直接发送接收有效,以测试最大速度,测试驱动程序pipemaxtranfer设置4096情况下USB最大写速度上升到822KB/S,在65535情况下998KB/S!。这样看起来应该驱动程序应该没啥问题了。 接下来还得再研究STM32的USB固件,估计做下优化可能可以提高速度,比方说拷贝采用DMA方式,采用其他更加优化的端点缓冲方式等。因为我用的是STM32 USB开发包中那个USART-USB的例子进行的修改,应该是先天不足还有不少可以优化的地方吧。另外大家所说的Mass Storage那个例子应该速度在端点设置缓冲机制等等方面有值得借鉴的地方吧,打算晚上好好看看。另外在固件优化方面还请大家继续多出出主意啊:) ---------------------------------------------------------------------------------------------- USB要提速 1、使用自定义的Bulk传输 2、增加驱动的Buffer ---------------------------------------------------------------------------------------------- 又热心帮助大家,我也是从中学习了不少知识,实在是感激:) 昨天晚上大致看了下Mass Storage的例子以及STM32的技术参考手册,晚上睡觉的时候仔细想了下(呵呵,发现好像睡觉的时候能安静思考)。 主机向STM32发送数据的时候,传输的速度是457KB/S,而当我把STM32 用于接收的EP3_OUT回调函数中PMAToUserBufferCopy这2句话去掉的话速度就上升到了822KB/S,想来还是USB固件的处理速度限制了USB传输的提升,毕竟主机是每发送64字节就等待USB设备回应,当USB设备没有完成相应的操作时状态始终是NAK,于是主机就一直重发,一直到设备完成相应的操作将端口置VALID后主机才能接着发下一个64字节。从457KB/S到822KB/S(当然这个速度是纯粹的传输速度实际上接收后是还要处理的)速度差别还是很大的,应该还有办法提升的。 上面几位说到改用MASS STORAGE的例子,大致看了下其实也是一样的,在BULK传输时候,都是采用一样的EP 单向BULK操作,64字节的管道尺寸,我现在的固件也是这样用的,没什么不同。问题不在于用哪个例程哪个设备类型,而应该在于怎么去提高BULK传输的处理速度上吧。 昨天在看STM32技术参考手册的时候18.5.3提到了双缓冲端点,实现所谓PING-PONG机制,可以应用在同步和批量传输,我想把现有的EP传输方式改成双缓冲机制,应该能提高BULK的传输速度吧。刚刚找了下资料 普通单缓冲机制的OUT过程: 1、主机发出OUT 2、设备接收该OUT包,检测缓冲区,当缓冲区由MPU占据时一直置NAK,主机不断重发数据包 3、当MPU放弃缓冲区占有(完成了相应的操作)后,置ACK,可接收下一个OUT包 4、主机发送下一个OUT包 ---------------------------------------------------------------------------------------------- 单缓冲模式就跟单线程一样, 一个一个排队依次顺序执行,因此速度受缓冲区占用情况的严重影响,尤其当单片机处理速度慢时更严重。 双缓冲端点机制:双缓冲机制有两块缓冲区在一个时间点上可分别由USB端点和MCU来占有 1、主机发送OUT1包 2、设备接收OUT1包并写入空闲的Buffer1,并置ACK,可以接收下一个OUT1包,同时buffer1的控制权可以交给MCU完成处理。 3、主机发送下一个OUT2包,设备将OUT2放入空闲的buffer2包,并置ACK,通知主机可以发送下一个OUT3包。 同时MCU继续完成上上一个OUT1包的处理后,释放BUFFER1的控制权,可以接下来占有buffer2进行处理 4、主机发送OUT3包,此时由于buffer1已经由MCU完成处理释放了控制器,设备接收OUT3包并放入BUFFER1中,置ACK,再通知主机可以发送下一个OUT4包 ... 由此可见双缓冲机制,依次交换2个缓冲区的所有权,看起来就类似与双线程一样,USB端点接收和MCU数据包处理是同时在进行的,减少了传输时候等待MCU完成接收包处理的等候,大大地提高了传输的效率。 现在打算把BULK改成双缓冲试试,看看对速度能有多大改善。遗憾的是在MASS_STORAGE没有采用双缓冲机制。原理是了解了,不过还不清楚固件该怎么具体怎么编程,哪里有BULK双缓冲传输的例子可以学习一下? ---------------------------------------------------------------------------------------------- 来自(http://bbs./forum-126-1.html) |
|