USB基礎知識掃盲
前言
本文將從USB的插入檢測、身份識別、資料傳輸三個方面對USB通訊整個過程掃盲,其中有些知識點的詳細資訊會放在文章最下面的附錄中供檢視,從而保證文章的整體簡潔。在進入主題之前,首先了解一下USB的一些基礎知識
USB的分類
-
按介面型別分
- 控制器/主機(controller/host)
- 裝置(peripheral)
- OTG(on-the-go),通過id線確定作為主機還是作為裝置
-
按照USB速度分
- 低速(low speed)
- 全速(full speed)
- 高速(high speed)
一、USB插入檢測
USB介面一般是4根線,VCC GND DM(D-) DP(D+)
- A:USB是如何檢測到裝置插入的
-
Q:主機端將DM DP接入下拉電阻;裝置端根據不同速度,將DM DP的某一根接上拉電阻,插入時通過壓差即可判定是否插入
- 低速裝置:在DM線上接入上拉
- 全速裝置:在DP線上接入上拉
- 高速裝置:在DP線上接入上拉,在主機對裝置進行復位後進一步的確認,詳情
二、USB身份識別
對於插入的USB裝置,主機需要傳送比較短的請求來確認裝置的身份、型別、速度等資訊,這個過程稱之為列舉
2.1 描述符
裝置的“身份”資訊儲存在描述符中。每個USB裝置中都有如下描述符。需要注意的是
- 一個USB裝置只能有一個裝置描述符
- 其他描述符都可以有多個,對應複合裝置,例如USB鍵鼠
-
裝置描述符(device description)
-
配置描述符(config description)
-
介面描述符 (interface description)
- 端點描述符 (endpoint description)
- 端點描述符
-
介面描述符
- 端點描述符
-
-
配置描述符
-
介面描述符
- 端點描述符
-
-
2.2 列舉過程
- 等待穩定:主機通過電平差檢測到裝置,等待100ms讓裝置電平趨於穩定
- 首次復位:HUB發起復位,讓裝置進入初始的地址0模式
-
首次查詢裝置描述符:GET_DESCRIPTOR 主機查詢裝置描述符,只要前8位元組 ==>
80 06 01 00 00 00 12 00
- 二次復位:在接收到裝置描述符前8個位元組後,再次重啟裝置
-
設定地址:SET_ADDRESS 主機下發設定地址命令,裝置獲取新地址 ==>
00 05 01 00 00 00 00 00
-
二次查詢裝置描述符:GET_DEVICE_DESCRPTOR獲取整個18位元組的裝置描述符 ==>
80 06 01 00 00 00 12 00
-
獲取配置描述符:GET_CONFIGURATION 獲取9位元組配置描述符 ==>
80 06 02 00 00 00 09 00
- 完成配置:SET_CONFIGURATION,
2.3 描述符詳解
搞懂了描述符,調好了列舉,就完成了USB通訊的一大半,下面就對描述符進行詳細的探索
裝置描述符 | 18 | 配置描述符 | 9 | 介面描述符 | 9 | 終點描述符 | 7 |
bLength | 1 | bLength | 1 | bLength | 1 | bLength | 1 |
bDescriptorType | 1 | bDescriptorType | 1 | bDescriptorType | 1 | bDescriptorType | 1 |
bcdUSB | 2 | wTotalLength | 2 | bNumInterfaces | 1 | bEndpointAddress | 1 |
bDeviceClass | 1 | bNumInterfaces | 1 | bAlterateSetting | 1 | bmAttributes | 1 |
bDeviceSubClass | 1 | bConfigurationValue | 1 | bNumEndpoints | 1 | wMaxPacketSize | 2 |
bDeviceProtocol | 1 | iConfiguration | 1 | bInterfaceClass | 1 | bInterval | 1 |
bMaxPackeerSize0 | 1 | bmAttributes | 1 | bInterSubfaceClass | 1 | ||
idVendor | 2 | bMaxPower | 1 | bInterfaceProtocol | 1 | ||
idProduct | 2 | iInterface | 1 | ||||
bcdDevice | 2 | ||||||
iManufacturer | 1 | ||||||
iProduct | 1 | ||||||
iSerialNumber | 1 | ||||||
iNumConfigurations | 1 |
附錄
F1、USB通訊協議詳解
學習協議我個人覺得應該還是從整體流程向下詳細到具體協議,上來就看最基本單元/協議會讓人一頭霧水,這段附錄的大體流程也是如此。傳輸概念->傳輸流程->基礎傳輸單元->傳輸流程控制->
F1.1 USB通訊概念
- 在USB的通訊中,有傳輸(transfer),事務(Transaction),包(packet)三級。包是最基礎的傳輸單元,與TCP/IP協議中的MAC層協議作用相同。
- 在一次傳輸中,由多次事務組成,每次的事務又由多個包組成
- 與眾多協議相同,較高階別的協議的報文是基於/內嵌在低階協議的報文當中的,在USB中也不例外,例如,包中預留了DATA位,其目的就是填寫報文
-
傳輸(transfer): 控制(control)、中斷(interrupt)、批量(bulk),同步(Isochronous)
-
事務(transaction):傳輸方向、流程控制
-
包(packet):
- 令牌(Token):IN、OUT、SETUP、SOF,前導包,用於確認本次事務的方向、目的等,是每次事務必須要有的包。
- 資料(data):DATA0、DATA1、DATA2、MDATA,夾帶資料
- 握手(handshake):ACK、NAK、STALL、NYSET,作為應答、狀態回覆
-
-
F1.2 一次完整傳輸過程
下圖為一次完整的獲取裝置描述符的過程
-
傳輸:獲取裝置描述符
-
設定事務:主機向裝置下發 ->
80 06 00 01 00 00 40 00
- 令牌包 –> :SETUP型別
- 資料包 –> :由於令牌是SETUP型別,所以主機緊接著下發資料包,DATA0型別
- 握手包 <– :裝置收到資料包,回覆應答
-
輸入事務:裝置向主機上發 ->
12 01 00 01 DC 00 00 10 71 04 F0 FF 00 01 00 00
- 令牌包 –> :IN型別,主機準備好,裝置可以上發資料
- 資料包 <– :DATA1型別:DATA0與DATA1在傳送資料時需要交替,DATA中夾帶裝置描述符
- 握手包 –> :主機收到回覆,向裝置應答
-
輸出事務:無
- 令牌包 –> :OUT型別
- 資料包 –> :DATA0型別,再一次切換為DATA0,沒有需要傳送給裝置的
- 握手包 <– :裝置收到資料包,回覆應答
-
F1.3 基礎傳輸單元:傳輸基本單元 — 包(packet)
不同包的組成部分如下表所示,數字為每一個欄位所代表位數。結合上面的完整流程可以更輸入的理解包的概念。
Token 令牌包 | SYNC | PID | ADDR | ENDP | CRC5 |
8/32 | 8 | 7 | 4 | 5 | |
Data 資料包 | SYNC | PID | DATA | CRC16 | |
8/32 | 8 | 0-1023 | 16 | ||
Handshake 握手包 | SYNC | PID | |||
8/32 | 8 | ||||
SOF 起始包 | SYNC | Frame Number | CRC5 | ||
8/32 | 11 | 5 |
- SYNC欄位:為固定,FS/LS為8位,HS為32位
- PID欄位:決定了該包的型別,例如Token包的SETUP,IN,OUT,資料包的DATA0,DATA1,握手包的ACK,NAK等
- ADDR欄位/ENDP欄位:前面說過,一個裝置只有一個裝置描述符和多個終點描述符,這兩個欄位就可以在多個裝置中準確的找到目標裝置以及裝置中的目標終點,類似TCP/IP中的IP與PORT
-
SOF包:在Token包之前傳送,Frame Number為主機內部自增序列號,不斷迴圈
- FS/LS:每1ms傳送一次
- HS:每125us傳送一次
- EOF:EOF不屬於欄位或者資料,而是在每個包最後加上2個資料位寬的SE0訊號(DM DP都為低),用於表示包的結束
F1.4 傳輸流程控制 — 事務(Transaction)
在分析那個裝置描述符的流程時會發現,必須在每次事務的開始,要使用Token(令牌包)確認該次事務的傳輸“基調”。原因在於,USB是半雙工,DM DP並非獨立工作,所以採用“三段式”通訊,保證匯流排不會衝突
- 令牌包(Token):主機發起
- 資料包(Data):根據令牌包中的方向,由主機發起(OUT/SETUP)或者裝置發起(IN)資料包
- 握手包(Handshake):資料包接收方發起握手包,返回狀態,包含ACK NAK STALL狀態等。
- 不能中斷:USB的每次事務是“堵塞”,必須該事務完整後才能做其他事務
- 狀態判斷:之前的舉例當中,每次傳輸都是成功的回覆了ACK,可以看到,上圖中,事務發起了三次IN的Token包,裝置才傳送了下一幀資料。不會因為裝置忙就退出事務。
- 流程控制: 下發/接收資料、控制進出方向、確認回覆
F1.5 傳輸(Transfer)
終於說到頂層部分了,有點耐心馬上就說完了,首先傳輸分為以下幾種方式,對應不同需求
傳輸方式 | 令牌包 | 資料包 | 握手包 | 特點及醫用 | 特殊性 |
控制 | ✔ | ✔ | ✔ | 列舉過程中使用 | 多次事務,簡單的下發命令+回覆需要2次事務6個包 |
批量 | ✔ | ✔ | ✔ | 資料量大,要求準確性,常用於U盤等裝置 | 多次事務,DATA0/DATA1交替 |
中斷 | ✔ | ✔ | ✔ | 資料量小,要求固定頻率,常用於USB鍵盤滑鼠 | 與批量相似,主機會按照固定間隔向裝置發令牌包 |
同步 | ✔ | ✔ | × | 資料量大,要求低延遲,常用於USB攝像頭、音效卡 | 無握手包的批量傳輸 |
F1.5.1 控制傳輸(Control Transfer)
控制傳輸常用於USB列舉階段,讀取裝置描述符、設定地址等少量頻繁的工作。上面舉的獲取完整裝置描述符就是一個非常典型的控制傳輸過程,分為以下幾個階段
- 建立階段:SETUP事務,發下指定命令,裝置應答
- 資料過程:裝置等待主機發起IN事務,並將資料上傳,主機回覆應答
- 狀態過程:確認完成,這個階段傳輸方向必須與資料傳輸階段相反,資料傳輸是IN,確認就應該用OUT。
F1.5.2 批量傳輸(Bulk Transfer)
- 區分方向,有批量讀與批量寫,不能同時執行
- 一次批量傳輸由多次事務組成
- 傳輸過程中資料包型別DATA0/DATA1不斷切換,如果發生錯誤,則主機會要求重傳
F1.5.3 中斷傳輸(Interrupt Transfer)
中斷傳輸在資料傳輸方面與批量傳輸相同,重點在於,主機對中斷傳輸裝置必須保持固定掃描間隔,在裝置描述符中標註了該掃面間隔。USB匯流排即使被其他裝置批量傳輸佔用,也會在完成中間抽空向中斷傳輸裝置下發令牌
F1.5.4 同步傳輸(Isochronous Transfer)
因為要求實時性,對資料準確性不是很敏感,所以同步傳輸中的事務是沒有握手包的,如下圖
F2 USB通訊請求 Request
命令 | bmRequestType | bRequest | wValue | wIndex | wLength | Data |
GET_STATUS | 0 | 無 | ||||
CLEAR_FEATURE | 1 | 無 | ||||
SET_FEATURE | 3 | |||||
SET_ADDRESS | 5 | 裝置地址 | 0 | 0 | 無 | |
GET_DESCRIPTOR | 80H | 6 | 描述符型別+索引 | 0/languageID | 描述符長度 | 描述符 |
SET_DESCRIPTOR | 7 | |||||
GET_CONFIGURATION | 8 | |||||
SET_CONFIGURATION | 00H | 9 | 00xxH 配置值,高位元組固定00 | 0 | 0 | 無 |
GET_INTERFACE | 10 | |||||
SET_INTERFACE | 11 | |||||
GET_STATUS | 12 |
bmRequest欄位
D7 | D6-D5 | D4-D0 |
0:OUT 1:IN |
00:標準請求 01:類請求 10:使用者自定義 |
00:裝置 01:接 02:端 03:其他 |