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

工程师笔记 |USB发送数据时出现迟滞现象

[复制链接]
STMCU-管管 发布时间:2021-11-9 10:16
问题描述

" L6 n3 I" s* e& g客户反馈,使用STM32F446的高速USB外设,即USB_OTG_HS外设,且使用内置全速PHY。客户的产品USB用做device,自定义HID类,当连接带UOS操作系统的HOST时,会发现当前数据并没有成功发送,但是会发送上一次的数据,即发送数据出现”迟滞”现象。但在Windows下却没有出现此类问题。另外,客户同时还使用了STM32F446上的USB_OTG_FS外设,且此外设做同样的事一切正常,目前此问题只出现在USB_OTG_HS外设上。, Q& W1 o7 ?; H$ a, G0 m. j
' Y6 I- U9 P  k% E2 J
问题查找

: k0 ^( E2 H+ W$ E! Y刚开始猜测是长度问题,即发送最大包长需要再发送一次空包。但客户反馈他们的发送长度为62个字节。于是去客户现场使用USB协议分析仪采数分析,发现一切通信正常。& q( l* A( G& |% t" S! B% Q3 g

8 f( @& M) E( t; \4 ^- z; p通过查看客户演示重现问题的过程,发现在正常时是一切OK的,只在进行USB拔插时才发送问题。应用程序不断发送数据的过程中拔掉USB线,然后再次插上,在此过程中应用程序一直尝试发送数据。当USB线重新连接上且重新枚举成功后,“迟滞”现象则重现了,即每次应用程序调用发送接口实现发送的是上一次尝试发送的内容。
/ E* j; i: }' V* T/ h; W5 \: o! S# ~9 c. y* x9 K- Z
调试客户的程序,发现当USB线拔掉后,应用程序还会往USB IP对应的发送FIFO内写入数据,这其实是不对的。按理USB线拔掉后USB的状态应该恢复到默认状态,) G7 i9 C$ U; c  h4 D9 v( d; ?% V/ e
/ _7 D; @0 F) j, n
即pdev->dev_state=USBD_STATE_DEFAULT. 但实际上,通过调试发现此状态在USB线拔掉后是suspend状态。1 H$ F$ S: D/ S
6 g( A, ]. q" Z8 n, ?& |
那么为什么会是这样的呢?. Z4 |# Z* e, I8 w0 ^7 U0 s& Z9 P
: n& t3 {* @( W
于是立即想到Vbus sensing功能。马上与客户硬件工程师核对,原来客户产品的USB_OTG_HS的Vbus_sensing脚是悬空的,并没有连接Vbus,但是客户的USB_OTG_FS外设却又是连接了。于是客户的产品两个USB口,同样的工作,一个USB口 正常,另一个USB口却会出现问题。
; r8 M! C% Q, @" X  J5 o) Y
3 V2 L: T3 x- `! A9 x' a4 G7 n
问题分析
5 ~' \; Y" c6 r' U7 m& A
差异找到了,接下来就是分析由此如何造成问题的。! y) N! D# Z/ {# I9 S! u- H
( T. t& L  K2 d5 J: R4 a3 g9 W
由于USB_OTG_HS并没有真正实现Vbus sensing功能(因为没有硬件连接),于是当USB线断开时,应用程序并不能准确地检测到断开事件(Disconnected),只会出现suspend,应用程序是无法直接的区分真正的suspend和USB线断开连接的。当应用程序有数据需要通过USB口发送时,如果当前是suspend状态,那么它会首先唤醒USB总线然后再发送数据:6 L1 [4 a/ `( l1 N/ h1 d8 h  [  v8 \
14.png
Figure1

- n% ~4 H( h, C- J, ?而这样发送远程唤醒信号时,device本身会产生一个resume中断,于是在resume中断回调函数内:
8 j6 d; Z- w1 j+ X9 A; T2 ^( [3 Q
15.png
Figure 2

0 h9 l5 H7 l" f3 T$ s如上所示,程序会将dev_state错误地恢复到上一次状态,即正常状态USBD_STATE_CONFIGURED, 如此一来,程序就错误地往USB IP的内的发送FIFO写入数据了,即使此时由于USB线已经断开而导致无法真正发送成功,但USB IP的内置发送FIFO此时是有了数据的。
2 d& |& ^# T+ ]8 n/ C& B

: O5 w/ j3 Q- r; G1 I4 e' i通过调试,查看OTG_DTXFSTS1寄存器相应端点1对应的发送FIFO的剩余空间可知,这个时候的发送FIFO的确实有数据的。接下来是USB线插上重新枚举,那么为什么USB重新枚举后还会再现问题呢?通过设置断点发现,在USB成功重新枚举过后,通过OTG_DTXFSTS1寄存器指示,发送FIFO内容并没有清空,于是在接下来发送数据时,永远都是实际上发送的是上一次写入到FIFO中的数据。
$ t- X% [. R$ V  B, d/ [" k' S6 y+ s7 s7 f! D  ~. Z5 ^* {
问题已经找到

1 k  }# @3 v$ ~
问题解决
▼于是解决方法就很容易找到了▼
8 G! q8 k- J: w
在USB重新枚举过后在合适的地方将端点1对应的发送FIFO清空一下即可。
2 F1 P- C1 d( M0 n% R! P$ ]
16.png
Figure 3
% n( p' P; C' J
问题总结
9 z+ r* d; N1 }: W5 [8 p" s
在客户的这个案子中,由于USB_OTG_FS连接了VBUS SENSING脚,当USB线拔掉后,会产生正确的disconnect中断,USB device的状态也会正确地切换到default状态,从而过滤掉应用程序想要发送的数据,因此并不会出现类似问题,因此,在客户的产品设计中,建议硬件千万不要忘了连接vbus引脚,即使在想省IO引脚的情况下,这样容易造成对软件的开发诸多不便.7 V& }. H, `0 a9 U& N# X8 y) m5 p% N
. }2 ?' o4 c# W, Q: v6 T6 h
在USB的状态处于非configured状态时,最好不要往发送FIFO写入数据,应用程序应该想办法将这些数据过滤掉。
: K! t% {9 j( s+ c& H1 `
赞 收藏 1 评论0 发布时间:2021-11-9 10:16

举报

0个回答

所属标签

相似技术帖

官网相关资源

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