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

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以上,我现在的速度应该还有很大的提升才是。
& [. ?* _* P! M8 {6 r) z$ C* I3 U* h0 J. x' t- q& n/ e
看看程序,发现
' Z  m/ M6 l( x$ o8 [- N1 _void EP3_OUT_Callback(void)//EP3 OUT的回调函数,当EP3接收到数据时候中断调用该函数 / _" H+ x5 E9 l& U
{
! `# h' @7 `4 h: [' v8 y* z# d, J8 acount_out = GetEPRxCount(ENDP3);//获得接收到的数据长度 3 x6 m3 {. _. K7 {; b
PMAToUserBufferCopy(buffer_out, ENDP3_RXADDR, count_out);//将数据从USB EP3 RX的缓冲区拷贝到用户指定的数组中 : [/ R- {! A  w; A! N7 ]
SetEPRxValid(ENDP3); //完成拷贝后置有效状态,从而EP3发送ACK主机可以进行下一个数据包的发送 ) O0 W( j9 t' \2 |+ P9 c
} 8 n8 J3 r6 l+ ~* O# u8 ~) E
试着将PMAToUserBufferCopy这句注释掉(这样STM32就不处理接收到的数据了)后再测试速度,惊奇地发现速度竟然达到了997KB/S!晚上仔细想了想,数据肯定是要使用的,这个数据拷贝的过程的时间消费总是少不了的;由于通常情况下USB设备BULK数据接收的步骤就是:接收到数据,置NAK->将缓冲区数据拷贝到用户区(用户处理过程)->发ACK通知主机完成了完整的接收可以发送下一个->主机发送下一个,按照以上的步骤USB接收一步步的进行,只要STM32不完成数据处理,状态就一直是NAK,主机就会不停地发送该数据包,浪费了带宽,因此就会导致我上面最大速度500KB/S难以再增加的情况!不甘心啊~~: I8 t, n2 G; K* o3 B/ r! v
昨天晚上又仔细研究了STM32的技术参考手册的USB章节内容,里面提到BULK可以采用双缓冲机制(PING-PONG)进行处理,正好可以解决上面的情况。双缓冲机制的原理就是分配2块接收缓冲,STM32的用户处理和USB接口可以分别交替占用2个缓冲区,当USB端点接收数据写其中一个缓冲区的时候,用户的应用程序可以同时处理另一个缓冲区,这样缓冲区依次交换占有者,只要用户处理程序在USB端点接收的时间片段内完成处理,就能够完全不影响USB的通讯速度!% `- Q8 R# U: i6 c2 G! i/ C5 @( U

& k- ]4 E7 K7 f6 u1 {! r程序部分修改 & h1 f7 v$ R' R8 O
一、EP3_OUT的设置修改,
1 B# ~: d3 P% p6 x3 N% j) a//ZYP:修改EP3为BULK双缓冲方式-------------------------
% F( G' O/ Y1 @6 x. e& T5 ?, _SetEPType(ENDP3, EP_BULK); 2 \/ G- D$ k. e: c
SetEPDoubleBuff(ENDP3);
/ Y0 E4 T$ f3 u( mSetEPDblBuffAddr(ENDP3, ENDP3_BUF0Addr, ENDP3_BUF1Addr);
2 d* x& G$ S0 }- |3 @# Y: W0 sSetEPDblBuffCount(ENDP3, EP_DBUF_OUT, VIRTUAL_COM_PORT_DATA_SIZE); 8 H! X, O& E* n. c
ClearDTOG_RX(ENDP3);
% l4 M6 K9 x# X( K" b6 yClearDTOG_TX(ENDP3); ! p5 `$ p  g$ y# y5 y$ r
ToggleDTOG_TX(ENDP3);
( r7 R8 u' X( U3 M# x0 n$ Q' Y- iSetEPRxStatus(ENDP3, EP_RX_VALID);
$ N* S( B! f% g7 s2 v# jSetEPTxStatus(ENDP3, EP_TX_DIS); 3 _! _: k: b! G0 e' f" A
//------------------------------------------------------ ; X. A' `/ w6 ~7 _

! M& n: d# S) P8 F二、EP3_OUT回调函数的修改
3 ^' O) D' m* t* p3 X6 \+ [* J' ovoid EP3_OUT_Callback(void) % {0 i$ S2 A% g$ L4 t* D& Q
{ 6 Y' K' D$ H& S8 L( b- T9 A
//ZYP:以下是修改成EP3双缓冲OUT后的处理函数 4 ^* E: h0 I/ H' p" V1 G. a. i
if (GetENDPOINT(ENDP3) & EP_DTOG_TX)//先判断本次接收到的数据是放在哪块缓冲区的
5 _# }. Y  e, g  r' `& X" D{
0 y8 y6 R5 M% ?1 s2 V3 g. tFreeUserBuffer(ENDP3, EP_DBUF_OUT); //先释放用户对缓冲区的占有,这样的话USB的下一个接收过程可以立刻进行,同时用户并行进行下面处理 9 ]7 a: \  p/ S% m. ~( M+ X
count_out = GetEPDblBuf0Count(ENDP3);//读取接收到的字节数
) N5 n5 E! C! c6 hPMAToUserBufferCopy(buffer_out, ENDP3_BUF0Addr, count_out);
; s- f. {: r& g} $ _7 N, t. A: S3 @9 K3 S* q3 p
else   i8 V" b3 Q, N* ~4 L0 I9 K2 Q
{ 5 \, m& r# |- ^* N$ n$ [" f
FreeUserBuffer(ENDP3, EP_DBUF_OUT); ! }. d$ S, }1 f, ~0 U
count_out = GetEPDblBuf1Count(ENDP3); , z- z8 t  u8 s1 q: z
PMAToUserBufferCopy(buffer_out, ENDP3_BUF1Addr, count_out);
7 D1 b6 z  }. Q3 j/ |9 z" W}
2 [8 x' O6 M. J5 e  ]} ( G! G; Z+ X3 ^( L- G
3 J, U* t( ~% c7 e! B- r
经过上面的修改,终于解决了STM32在处理接收数据时导致主机等待的情况,用BUS HOUND软件测试了下 + j$ U! N3 [) Y
哈哈,这下终于爽了。 * ^8 N& q; m0 |3 X; M- ?+ u
PS:上面的FreeUserBuffer(ENDP3, EP_DBUF_OUT); 这句话的上下位置是关键,如果放到函数的后面,则仍旧会有主机等待STM32处理数据的情况,速度仍然是500KB/S!
  S( n% |, m7 k# a9 Q* `. L+ }8 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微秒,就不会导致缓冲区竞争的情况。
' r* P$ g0 ]/ R; X7 S+ [4 V8 E1 H/ ~. j8 ?* {; Y9 y; d
出处: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)
2 [4 _( ]8 N9 E) |6 c{% _6 e/ x2 {; }" k
}
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
# ?8 G6 x' H5 y. b能否再快一些?
慎微 回答时间:2019-12-17 08:48:07
感恩啊,值得参考
zhaoyunme0 回答时间:2020-1-4 14:35:48
值得参考
qindaotang 回答时间:2021-2-17 16:40:34
源代码可以分享一下吗?0 y! ]! L" ?) G2 [

所属标签

相似技术帖

官网相关资源

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