你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 USB改双缓冲后,STM32的OUT接收速度到了1MB/S!

[复制链接]
endlesswind 发布时间:2008-9-3 17:45
前天测试自己编写的USB驱动程序时候发现从主机到STM32的OUT传输(主机到设备)速率竟然只有最高33KB/S,实在是晕死了。经过研究后发现是驱动程序中设置的PIPE MaxTransferSize参数的关系,原先设置64只能33KB/S,后参考其他USB设备驱动程序的值,设置成了65535,再测试USB OUT的速度,达到了500KB/S,终于解决了驱动程序的瓶颈。不过算下USB 2.0全速的通讯速率是12Mb/S,排除掉CRC、令牌、SOF等等开销怎么也应该不止最大500KB/S啊。到网上看了看,基本上应该能达到600KB/S~700KB/S以上,我现在的速度应该还有很大的提升才是。
/ D1 d% O1 ^2 m  G0 u
. l( S, W0 d+ Y- F" L* V看看程序,发现
3 t0 k2 N) g! ~  @5 Nvoid EP3_OUT_Callback(void)//EP3 OUT的回调函数,当EP3接收到数据时候中断调用该函数 ( r) X, w; c0 y+ N8 ]
{ & f; D# C# [! w" T* H- d# U7 n6 N" P
count_out = GetEPRxCount(ENDP3);//获得接收到的数据长度 $ d% F: s" k' B- ?8 n3 f1 b" \
PMAToUserBufferCopy(buffer_out, ENDP3_RXADDR, count_out);//将数据从USB EP3 RX的缓冲区拷贝到用户指定的数组中 & ?- h  H2 R: M7 F
SetEPRxValid(ENDP3); //完成拷贝后置有效状态,从而EP3发送ACK主机可以进行下一个数据包的发送 ' E- w5 }7 m! ^6 Z+ i4 c' s/ ~
}
/ \* t9 _3 E7 W" }试着将PMAToUserBufferCopy这句注释掉(这样STM32就不处理接收到的数据了)后再测试速度,惊奇地发现速度竟然达到了997KB/S!晚上仔细想了想,数据肯定是要使用的,这个数据拷贝的过程的时间消费总是少不了的;由于通常情况下USB设备BULK数据接收的步骤就是:接收到数据,置NAK->将缓冲区数据拷贝到用户区(用户处理过程)->发ACK通知主机完成了完整的接收可以发送下一个->主机发送下一个,按照以上的步骤USB接收一步步的进行,只要STM32不完成数据处理,状态就一直是NAK,主机就会不停地发送该数据包,浪费了带宽,因此就会导致我上面最大速度500KB/S难以再增加的情况!不甘心啊~~4 h8 o( B% J7 |( J3 M6 N
昨天晚上又仔细研究了STM32的技术参考手册的USB章节内容,里面提到BULK可以采用双缓冲机制(PING-PONG)进行处理,正好可以解决上面的情况。双缓冲机制的原理就是分配2块接收缓冲,STM32的用户处理和USB接口可以分别交替占用2个缓冲区,当USB端点接收数据写其中一个缓冲区的时候,用户的应用程序可以同时处理另一个缓冲区,这样缓冲区依次交换占有者,只要用户处理程序在USB端点接收的时间片段内完成处理,就能够完全不影响USB的通讯速度!
) F/ E1 @/ d6 E/ Y6 [# ?2 g 9 I4 G, b9 z( ~6 F* k1 a, J, }: `
程序部分修改
7 X' b* e/ ?0 Q. k/ R4 B! w1 _一、EP3_OUT的设置修改,
6 q! I% u9 R0 n' D2 ~//ZYP:修改EP3为BULK双缓冲方式-------------------------
# b8 E6 O0 k& X# H$ c- hSetEPType(ENDP3, EP_BULK); # R, J2 _! |' ?  E5 a% P9 `1 Y
SetEPDoubleBuff(ENDP3);
8 _, s$ n0 B5 p* [SetEPDblBuffAddr(ENDP3, ENDP3_BUF0Addr, ENDP3_BUF1Addr); 3 Q$ u/ s$ E) c$ W
SetEPDblBuffCount(ENDP3, EP_DBUF_OUT, VIRTUAL_COM_PORT_DATA_SIZE);
) w/ I9 ~9 n! ^: LClearDTOG_RX(ENDP3); ) o. Y( w4 {8 s7 Z$ Y
ClearDTOG_TX(ENDP3); ' E8 i* U' j% B4 |" c
ToggleDTOG_TX(ENDP3);
8 ]( @& o7 Q$ \6 B4 l. s* iSetEPRxStatus(ENDP3, EP_RX_VALID);
% ^) m  K# R; W+ n0 eSetEPTxStatus(ENDP3, EP_TX_DIS);
& y' G. y+ F# t5 m8 L2 m5 r" w- ]- B# C//------------------------------------------------------
( `+ G5 P% u9 @# a* o2 K, o& q$ x1 [  p
二、EP3_OUT回调函数的修改
; e5 e& P1 \; T- q* @void EP3_OUT_Callback(void)
0 q- p/ S% X6 X{ ) ]. {4 b5 }% S5 L5 a0 o- h- T
//ZYP:以下是修改成EP3双缓冲OUT后的处理函数
  U# n# n& J& Qif (GetENDPOINT(ENDP3) & EP_DTOG_TX)//先判断本次接收到的数据是放在哪块缓冲区的 4 w, S, r2 J" N1 C( z$ k
{
; l4 ^6 X- d8 P2 K3 sFreeUserBuffer(ENDP3, EP_DBUF_OUT); //先释放用户对缓冲区的占有,这样的话USB的下一个接收过程可以立刻进行,同时用户并行进行下面处理 4 B) q5 v! {8 m0 p/ p( \* t7 f  I4 Q
count_out = GetEPDblBuf0Count(ENDP3);//读取接收到的字节数   D8 l# I* ]" Q8 D! {6 M  o
PMAToUserBufferCopy(buffer_out, ENDP3_BUF0Addr, count_out);
: C/ Z- j4 H* ^! p}
  c- w9 h& ]4 t8 B6 C6 m- H. Telse
! @( N6 U0 c% Z. g! ]{ " I1 J( N* V  Q1 s- b
FreeUserBuffer(ENDP3, EP_DBUF_OUT);
- g2 L1 W4 x1 O3 o% h4 l& T  }count_out = GetEPDblBuf1Count(ENDP3);
3 o. i7 ]3 l' L2 B2 i4 ~) b' PPMAToUserBufferCopy(buffer_out, ENDP3_BUF1Addr, count_out);
- ]: ~/ ~; [' W$ U}
* l2 N! o, I  {0 F% Y: u, p}
; t1 U; ]5 k6 b* @' d5 {6 Q
' T0 V/ p  {; @6 }) B经过上面的修改,终于解决了STM32在处理接收数据时导致主机等待的情况,用BUS HOUND软件测试了下
: A' ]/ t" M6 T2 o7 `) n, L0 F哈哈,这下终于爽了。
( I0 N+ j, F" z  I' o+ Q$ n4 sPS:上面的FreeUserBuffer(ENDP3, EP_DBUF_OUT); 这句话的上下位置是关键,如果放到函数的后面,则仍旧会有主机等待STM32处理数据的情况,速度仍然是500KB/S! / s, A% W/ j; s! X2 s7 {( a
把这句话放在拷贝函数的前面的话就真正把双缓冲PING-PONG机制用起来了。大致算了下PMAToUserBufferCopy(buffer_out, ENDP3_BUF1Addr, count_out);这句话当count_out为最大值64的时候STM32执行需要302个周期,72MHZ情况下约4.2微秒执行时间,而USB传输按照12Mb/s的线速度传输64字节的数据至少也得40微秒,因此只要PMAToUserBufferCopy的时间不超过40微秒,就不会导致缓冲区竞争的情况。
8 U1 T2 R. r, T2 d
, l1 f1 @& I: L, l' V( n: k) ?出处:alien2006
收藏 2 评论7 发布时间:2008-9-3 17:45

举报

7个回答
oktigerxia 回答时间:2009-9-23 17:22:06

RE:STM32 USB改双缓冲后,STM32的OUT接收速度到了1MB/S!

你好!最近我也在调试USB速度,很慢,我用的是ST的例程,#define BULK_MAX_PACKET_SIZE  0x00000040 ,我试着把0x00000040改成0X0000FFFF,程序显示空间溢出,改成0X000000FF,usb也没法读写SD卡。奇怪的很,希望指点。而其例程中无EP3_OUT_Callback(void)//EP3 OUT函数的定义,#define  EP3_OUT_Callback  NOP_Process;void NOP_Process(void)
. ?: `& ^$ L$ l# b: r{
' |: ?3 d. x* u  m& ~; P}
chenhui8888ren 回答时间:2009-11-7 09:47:57

RE:STM32 USB改双缓冲后,STM32的OUT接收速度到了1MB/S!

学习中
啊抠 回答时间:2011-1-7 17:33:28

回复:STM32 USB改双缓冲后,STM32的OUT接收速度到了1MB/S!

不可能到65535吧,楼主的例程是怎样的可否一观~~
aiherong 回答时间:2019-12-16 23:11:28
检测电压时就决定了USB高低速模式,DM与DP
7 G  U8 V2 v) @能否再快一些?
慎微 回答时间:2019-12-17 08:48:07
感恩啊,值得参考
zhaoyunme0 回答时间:2020-1-4 14:35:48
值得参考
qindaotang 回答时间:2021-2-17 16:40:34
源代码可以分享一下吗?. B4 e4 d/ B7 k- f, k9 j

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版