1. 程式人生 > >usb-otg-除錯心得

usb-otg-除錯心得

相關文章

僅僅看了半天SPEC寫的筆記,有些亂,等除錯完畢再次整理,思路不是很成熟,推測成分較多,可能有不對的地方,歡迎拍磚交流指正。 1. 概要 OTG裝置使用插頭中的ID引腳來區分A/B Device,ID接地被稱作為A-Device,為連線時候的USB Host,A-Device始終為匯流排提供電力,ID懸空被稱作為B-Device,為連線時候的USB Device,裝置的USB Host/USB Device角色可以通過HNP切換。
OTG裝置連線時不能跨越USB Hub,如果跨越USB Hub則失去HNP功能。
這裡要注意A-Device/B-Device與USB Host/Device不是一回事沒有必然的繫結關係A-Device就一定要是Host,A-Device只是連線時的Host可以通過HNP切換,切換完畢A-Device變成USB Device但是仍然為匯流排提供電力。
2.裝置型別
Embedded Host:提供標準的A插座,普通的USB Host並帶有TPL(支援裝置列表)
OTG Device:使用Micro AB插座,可以在執行時切換Host/Device。
僅外設B-Device:僅僅能作為外設的B-Device(分為插頭一體和插頭線纜分離的)。
注意:OTG Device在插頭插入後會先開啟VBus,如果沒有裝置連線則關閉VBus,並開啟ADP偵測,而Embedded Host則不會再次關閉VBus。
3.協議 SRP(Session Request Protocol):
B-Device使用。通過資料線上的脈衝,請求A-Device開啟VBUS並且開始一個Session。Session為從VBUS開啟到關閉這一段時間。 支援:A-Device允許迴應SRP,B-Device(包括僅能作為外設的B-Device),允許發起SRP。一個能夠支援HNP的B- Device應該能夠發起SRP。當A插頭插入時關閉VBus的Host必須支援迴應SRP,VBus總是開啟的Host不必響應SRP。
ADP(Attach Detection Protocol):
提供裝置檢測是否有對端裝置插入。 支援:任何OTG裝置,Embedded Host,支援SRP的B-Device允許ADP Probing,B-Device和僅能作為外設的B-Device還必須支援ADP Senseing如果他們支援ADP Probing。
HNP(Host Negotiation Protocol):
OTG裝置通過HNP來切換Host/Device角色。 當前的USB Host通過HNP Polling(類似Polling Hub)通過輪詢GetStatus()命令返回的資料中的Host request flag查詢對端裝置是否請求變為Host,Polling間隔為1-2秒。 噹噹前的USB Host決定允許B-Device轉變為Host以後通過SetFeature()開啟b_hnp_enable,本次Session結束後Host回到A-Device手裡。
4.裝置框架
OTG描述符 在裝置列舉時,A-Device通過GetDeor向B裝置請求OTG描述符。OTG描述符也應當作為GetConfiguration()的一部分返回。其中的bmAttributes標示B-Device是否支援ADP/HNP/SRP
標準裝置特性,通過SetFeature()設定。 b_hnp_enable
設定此特性,顯示B-Device被允許進行HNP,A裝置必須在T(HOST_REQ_SUSP)時間內掛起匯流排。 a_hnp_support
早期OTG版本的相容特性,設定這個特性指示B-Device對端的A-Device支援HNP。A-Device應當對B-Device設定此特性如果A-Device支援HNP。 a_alt_hnp_support
廢棄
GetStatus()
其中資料部分OTG Status最低位為Host Request flag,指示當期的USB Device角色期望變為USB Host角色。
5.一般連線過程(Host -> Device)
OTG Device /Embedded Host 與 僅作為外設的B-device(帶A插頭型) Host端檢測到A插頭插入,停止ADP,開啟VBus,因為B-Device的A插頭與裝置作為一體,此時B-Device必定與A插頭連線,Host檢測到外設連線,開始列舉。
 
OTG Device/Embedded Host 與 僅作為外設的B-device(A插頭為線纜連線) Host段檢測到A插頭插入,停止ADP,開啟VBus,如果B-Device是線纜連線完畢在將A插頭插入則整個連線過程與上面無異,因為此時B-Device可能還沒有插入插頭,則裝置連線超時,VBus再次關閉,等待下一次ADP的改變(線纜連線完畢),再次開啟VBus,此時開始正常匯流排列舉。
OTG Device 與 OTG Device Host端檢測到插頭插入,則開啟VBus,如果沒有外設檢測到,則關閉VBus,開啟ADP Probing,Device端檢測到插頭插入,則開啟SRP,如果線纜沒有插入,則SRP超時,Device端開始進行ADP Probing,當線纜連線完畢,Device端偵測到ADP變化,傳送SRP請求Host開啟VBus,Host迴應SRP並且開啟VBus,完成裝置連線。
6.OTG Device(Host/Device)與普通USB Host/Device OTG Device(Device)插入普通USB Host: SPEC指示OTG Device滿足所有USB外設條件,電器原理實現未查明。 普通USB裝置插入OTG Device(Host): OTG相容,但是電器原理實現未查明,對VBus的開啟,以及ADP和SRP的處理有疑問。在usb.org上有人問起這個問題,回覆只是講會識別並且相容,但是實現原理及監測細節未知。 原貼地址:
最新的一些思考和猜想:
1.ADP是OTG Device作為Host,既可以關閉VBus又能夠監測普通USB裝置的關鍵。
2.OTG Device作為Host如果不支援ADP,但是支援SRP的,VBus應當始終開啟(或者通過插入中斷?RootHub Polling),如果要關閉VBus則僅能支援會發起SRP的OTG Device,普通的USB裝置和不支援SRP的OTG Device,在Host沒有ADP的情況下無法在關閉VBus的情況下檢測到裝置(除了插入中斷)插入並且通過SRP開啟VBus。
注: OTG Device作為Host在A插頭插入時會嘗試開啟VBus,如果插入裝置線纜在A插頭插入時已經連線完畢,則在這次插入時,正常列舉。如果插入裝置線纜在A插頭插入時沒有連線,作為Host的OTG Device又不支援ADP,但是支援SRP,那麼插入裝置可以線上纜插入後發起SRP開啟VBus,如果插入裝置不支援SRP。則裝置工作不正常?
3.OTG Device在監測匯流排活動和裝置連線前會在插頭插入時首先檢測插頭(普通USB不會檢測插頭,因為不關心,OTG的ID引腳會起控制器中斷),從而決定OTG Device角色,並且通過ADP等待裝置連線,然後開啟VBus進行匯流排活動。
關於SRP與ADP 作為一個B-Device或者是普通的USB Device,怎樣開啟VBus進行匯流排列舉是他們的最終目的。 SRP為B-Device請求A-Device開啟A裝置的手段之一,而ADP雖然作為檢測插入裝置為目的但是有些EH/OTG Device會在ADP檢測到狀況以後不等到SRP的到來(或者說不支援SRP)就開啟VBus,倘若沒有裝置連線,再關閉VBus並且開啟ADP繼續偵測(僅限於OTG Device EH不會),更有甚者檢測完A插頭直接開啟VBus(ADP出來的較晚,很多早期的OTG控制器中,根本沒有ADP和HNP Polling的字樣,估計那時候可能SPEC裡面還沒有這些東西)這讓SRP顯得有些多餘,但是我們作為一個B-Device的時候還是應當在開始匯流排操作前發出SRP,保證不支援ADP只支援SRP並且插頭插入時不開啟VBus僅僅在受到SRP才打開VBus的控制器上,裝置也能進行正常列舉。





MUSBHDRC與 MUSBMHDRC是Mentor Graphics出品的相容支援OTG功能的IP Core被廣泛的應用於 TI ADI的多媒體處理器中。兩個IP的區別在於MUSBMHDRC帶有Multipoint功能,可以接HUB。下面是我在FPGA上除錯碰到的問題及解決,歡迎交流拍磚。
MUSBHDRC RTL V1.8版本 BUG及解決 1.中斷不會Pending MUSBHDRC在關閉EP中斷的情況下不會去置中斷位,這樣再次開啟中斷時,因為中斷沒有Pending,直接導致本次中斷丟失。而 Mentor的做法也相當的令人鄙視,竟然只是在Datasheet中悄悄的把原先版本Datasheet中的中斷會Pending的那句話悄悄的去掉。 解決: 只能在SOC級解決,Davinci的解決方法把相關的暫存器Shadow了一下,不允許操作原來MUSBHDRC中的相關中斷暫存器而轉而使用SOC提供的相關暫存器。
2.DMA部分的BUG MUSB系列的DMA模式分為3種。DMA MODE 0,DMA MODE 1 REQ MODE 0, DMA MODE 1 REQ MODE 1。 其中DMA MODE 1 REQ MODE 1在MUSBHDRC上無法正常工作,一旦FIFO裡有Packet,並且< MAXP 則不會再來中斷。 DMA MODE 1 REQ MODE 0在連續的發起DMA請求時候會掛住匯流排,導致系統鎖死,而且因為DMA MODE 1 REQ MODE 0必須知道資料總量的限制,在很多的USB上層的協議中都無法使用。 DMA MODE 0在Device方式時效率低下,不考慮。 解決: 只能在SOC級解決,可以見到Davinci和TUSB都沒有使用MUSBHDRC的DMA控制器,都是在SOC上做了一個DMA控制器實現相關DMA操作。
MUSBMHDRC 基本解決了MUSBHDRC中的相關BUG,並且增加了Multipoint功能。可惜Linux驅動中尚沒有端點複用及排程相關程式碼,所以目前仍然不可能支援太多數量的USB裝置。
關於ID Pin中斷 MUSB系列沒有提供ID Pin的中斷,而我們從Controller看到的A/B Device邏輯也相當的奇怪。在A-Device狀態下,寫DEVCTL.SESSION則PHY拉起VBUS,DEVCTL.B-DEVICE和 DEVCTL.VBUS Session才有效,也就是說我們必須開始Session軟體才能知道是目前A-Device還是B-Device,這在OTG狀態機的A- Device向B-Device狀態推進時會出現很大問題:驅動這邊會出現許多協議裡沒有的狀態變遷。這樣在OTG Device-> Host 時插頭髮生變化而軟體不知,沒人來Drive VBUS,直接導致啞炮熄火(有朋友說我的沒有啊,只是有時好用有時不好用,原因後面揭開)。而Host-> Device時,Host裝置拔出時停留在A_WAIT_BCON狀態,在換上B-Device插頭時狀態機沒有經過A_WAIT_BCON-> A_WAIT_VBUS_FALL-> A_IDLE->B_IDLE的變遷,直接導致驅動程式中狀態機狀態變遷異常,而Davinci採取了Timer不停地寫Session的方法來 Workaround,但是不是解決問題的根本,而我們又不能總是通過Session來檢測,最根本的解決方法就是外加一個ID Pin中斷來檢測插頭,同時推進狀態機。
詭異的Session Request中斷 在Datasheet中,這是一條僅僅會在Host方式下來的中斷,但是在實際使用中,這條中斷來的十分詭異,B-Device狀態下有時候會在插入B插頭時每隔3-5秒來一次,有時候又不來,有時候沒插插頭時也回來,飄忽。而驅動中收到Session Request中斷則立即Driver VBUS,這解釋了前面Device->Host時而好用時而失效的原因。 解決: 走正規的ID PIN檢測關閉此中斷,在檢測到A插頭插入時立即開啟Session -> Drive VBUS,這樣就不用關心對方裝置的SRP了。
關於Device方式下SetAddress的注意 按照Datasheet中的流程在收到Setup包的時候即可設定FADDR改變當前的Address,然後清掉RXPKTRDY並且置位 DataEND 回覆0包,並且使Controller進入控制傳輸的Status Stage,完成後來一個MC_INT中斷。實際則不然,如果這樣操作會導致MUSB Controller失去響應,在協議分析儀上看到Controller在接下來的Get Deor的SETUP Transaction中的IN Token中沒有任何回覆,或者回復一些NAK後,失去響應。
正確的操作方法為:收到SetAddress以後,不要立即設定FADDR,在Status Stage結束後來的那次中斷中設定SETUP包中的傳來的地址。
關於DMA MODE 1 REQ MODE 1 Device方式下DMA MODE 1 REQ MODE 1為相容性和效率最佳方式。然而在Host方式下只能使用DMA MODE 0。歸根結底在於DMA MODE 1 REQ MODE 1的結束條件< MAXP 倘若Host連續開啟兩個IN Transaction,每個IN Transaction大小為MAXP的倍數,則在DMA停止時無法區分兩個包,前一次IN Transaction因為結束時還滿足DMA MODE 1 REQ MODE 1的條件,直接導致DMA控制器將下一個IN Transaction的包已經收到了FIFO/URB中,如果所有IN Transaction 如果都能被MAXP整除,開始的那個URB豈不成一團漿糊了。
解決:控制器設計問題非BUG無法解決,使用DMA MODE 0。
關於Linux中的驅動程式。驅動位於drivers/usb/musb下。 程式碼中沒有端點複用和排程部分,因此Multipoint功能極大受限。Interrupt及Isochronous方式傳輸似乎有問題,尚未研究。
關於VBUS_ERROR的缺陷。 在一些需要電量較大的裝置插入時MUSB在寫入Devctl.Session時候VBus拉不起來,並且產生VBUS_ERROR中斷,接下來難堪的問題發生了,Controller居然切到B-Device狀態,再也不能通過寫Session拉起VBus。尚未找到恢復方法。、 轉載於: http://blog.csdn.net/ljzcom/article/details/8843597