1. 程式人生 > >USB協議學習(1)

USB協議學習(1)

最近在工作中,要求學習USB的通訊協議來解決一個USB與測試版連線不成功的小問題。之前未接觸過任何關於USB的知識,相當於現在什麼都是重新學習,現打算記錄一下自己的學習經驗與過程。

在剛接觸USB協議前,我是先閱讀了圈圈大神的《圈圈教你玩USB》前兩章作為入門的鋪墊。圈圈大神寫得很通俗易懂,並且在第一章裡介紹了很多關於USB協議的基本知識,所以整個閱讀下來很有收穫的。後面的章節因為硬體上的限制,所以也就沒有繼續再閱讀下去,而是選擇了手上現有的51增強型晶片與附帶的例程。

我的學習習慣是從知識的架構入手,手上有兩本關於USB協議的紙質書,與一份51開發板廠家提供的USB例程,就是這份例程無法識別我所接入的USB裝置,但是這份例程拿來作為入門卻是很不錯的。

經過一週多的摸索,我個人認為的USB協議的學習架構應該是從USB裝置接入到主機進行資料傳輸以及到拔出的過程,通過整理USB協議在這一過程中所執行的每一個步驟,來描繪屬於我的學習框架。整理材料如下:

1)   插入USB裝置

2)   主機的集線器識別到有USB連線,然後通過中斷的方式提醒主機,有USB裝置接入

3)   主機像集線器傳送GetPortStatus請求,讀取下行埠的狀態及狀態變化

4)   主機等待100ms左右,消除拔插抖動

5)   主機向集線器發出SetPortStatus請求,復位這個USB裝置,在裝置復位的過程中,集線器讀取USB裝置傳輸速度的型別

6)   10ms復位等待,復位成功後設備會進入預設狀態,主機與裝置通過端點0進行通訊(主要是列舉過程的通訊)

7)   主機通過端點0發出Get_Descriptor(Device)請求,這個請求只讀取裝置描述符的前8個位元組(用來確定端點0能傳輸的最大資料包長度,其實也可以通過直接告訴主機長度值來取消這一步的執行)

8)   主機通過端點0發出Set_Address請求,為裝置分配一個唯一的裝置地址。之後裝置將通過這個地址與主機進行資料的傳遞,除非USB拔除或者主機斷電這個地址才會被擦除。

9)   主機向新的裝置地址發出Get_Descriptor(Device)請求,讀取裝置描述符的全部資訊。

10)主機迴圈傳送Get_Descriptor(Configuration)請求,讀取USB裝置的全部配置資訊。一般主機第一次傳送這個Get_Descriptor(Configuration)請求只讀取前9個位元組,主要是為了獲取該配置描述符的全部長度。

11) 主機根據usb裝置的資訊選擇一個合適的USB裝置驅動

12) 載入驅動後,主機發送Set_Configuration(x)請求,為USB裝置選擇一個合適的配置,並要求裝置按這個配置進行設定自己。

(以上步驟完成了USB主機與裝置直接連線的過程,接下來則可以正常進行資料的傳輸)

13) 主機與裝置通過七種(IN事務、OUT事務、PING事務、SETUP事務、SOF事務、SPLIT事務、PRE事務)不同型別的傳輸事務來與不同傳輸速度的USB裝置進行資料的交換。其中每一次完整的資料傳輸都可以看做是一次事務。

14) 如果裝置與主機太長時間不進行資料傳輸,主機發送SetPortFeature掛起命令讓裝置將進入掛起狀態。

15) USB裝置拔出。首先集線器會禁止USB使用的埠,然後通過中斷告訴主機埠狀態有變化,然後主機發送GetPortStatus請求來了解情況,如果是拔出則進行斷開操作,並釋放USB裝置驅動以及其所佔用的資源。 

以上15個點就是我整理出來的關於USB協議學習的框架,在這個框架的基礎上,去解讀那一份例程裡的程式框架。USB協議自然不止這麼一點,但是框架完成了,剩下的就是通過理論與實踐的結合來一點點補齊其他細分的知識以達到對整個協議的理解。這一篇文章也是作為我學習USB協議的一個記錄,如果日後發現有什麼問題我會一點點修改的。因為是新手,我知道自己整理的這份材料自然還有很多不足的地方,我會一直記錄在工作中關於USB協議的學習過程,若有不足,望大家告訴我一聲。