問題描述
客戶反饋,使用STM32F446的高速USB外設,即USB_OTG_HS外設,且使用內置全速PHY。客戶的產品USB用做device,自定義HID類,當連接帶UOS操作系統的HOST時,會發現當前數據并沒有成功發送,但是會發送上一次的數據,即發送數據出現”遲滯”現象。但在Windows下卻沒有出現此類問題。另外,客戶同時還使用了STM32F446上的USB_OTG_FS外設,且此外設做同樣的事一切正常,目前此問題只出現在USB_OTG_HS外設上。
問題查找
剛開始猜測是長度問題,即發送最大包長需要再發送一次空包。但客戶反饋他們的發送長度為62個字節。于是去客戶現場使用USB協議分析儀采數分析,發現一切通信正常。
通過查看客戶演示重現問題的過程,發現在正常時是一切OK的,只在進行USB拔插時才發送問題。應用程序不斷發送數據的過程中拔掉USB線,然后再次插上,在此過程中應用程序一直嘗試發送數據。當USB線重新連接上且重新枚舉成功后,“遲滯”現象則重現了,即每次應用程序調用發送接口實現發送的是上一次嘗試發送的內容。
調試客戶的程序,發現當USB線拔掉后,應用程序還會往USB IP對應的發送FIFO內寫入數據,這其實是不對的。按理USB線拔掉后USB的狀態應該恢復到默認狀態,
即pdev->dev_state=USBD_STATE_DEFAULT. 但實際上,通過調試發現此狀態在USB線拔掉后是suspend狀態。
那么為什么會是這樣的呢?
于是立即想到Vbus sensing功能。馬上與客戶硬件工程師核對,原來客戶產品的USB_OTG_HS的Vbus_sensing腳是懸空的,并沒有連接Vbus,但是客戶的USB_OTG_FS外設卻又是連接了。于是客戶的產品兩個USB口,同樣的工作,一個USB口 正常,另一個USB口卻會出現問題。
問題分析
差異找到了,接下來就是分析由此如何造成問題的。
由于USB_OTG_HS并沒有真正實現Vbus sensing功能(因為沒有硬件連接),于是當USB線斷開時,應用程序并不能準確地檢測到斷開事件(Disconnected),只會出現suspend,應用程序是無法直接的區分真正的suspend和USB線斷開連接的。當應用程序有數據需要通過USB口發送時,如果當前是suspend狀態,那么它會首先喚醒USB總線然后再發送數據:
Figure1
而這樣發送遠程喚醒信號時,device本身會產生一個resume中斷,于是在resume中斷回調函數內:
Figure 2
如上所示,程序會將dev_state錯誤地恢復到上一次狀態,即正常狀態USBD_STATE_CONFIGURED, 如此一來,程序就錯誤地往USB IP的內的發送FIFO寫入數據了,即使此時由于USB線已經斷開而導致無法真正發送成功,但USB IP的內置發送FIFO此時是有了數據的。
通過調試,查看OTG_DTXFSTS1寄存器相應端點1對應的發送FIFO的剩余空間可知,這個時候的發送FIFO的確實有數據的。接下來是USB線插上重新枚舉,那么為什么USB重新枚舉后還會再現問題呢?通過設置斷點發現,在USB成功重新枚舉過后,通過OTG_DTXFSTS1寄存器指示,發送FIFO內容并沒有清空,于是在接下來發送數據時,永遠都是實際上發送的是上一次寫入到FIFO中的數據。
問題解決
▼于是解決方法就很容易找到了▼
在USB重新枚舉過后在合適的地方將端點1對應的發送FIFO清空一下即可。
Figure 3
問題總結
在客戶的這個案子中,由于USB_OTG_FS連接了VBUS SENSING腳,當USB線拔掉后,會產生正確的disconnect中斷,USB device的狀態也會正確地切換到default狀態,從而過濾掉應用程序想要發送的數據,因此并不會出現類似問題,因此,在客戶的產品設計中,建議硬件千萬不要忘了連接vbus引腳,即使在想省IO引腳的情況下,這樣容易造成對軟件的開發諸多不便.
在USB的狀態處于非configured狀態時,最好不要往發送FIFO寫入數據,應用程序應該想辦法將這些數據過濾掉。
來源:STM32單片機
審核編輯:湯梓紅
-
單片機
+關注
關注
6042文章
44617瀏覽量
637618 -
接口
+關注
關注
33文章
8691瀏覽量
151707 -
usb
+關注
關注
60文章
7979瀏覽量
265608 -
STM32
+關注
關注
2271文章
10923瀏覽量
357100
發布評論請先 登錄
相關推薦
評論