通用串行總線(Universal Serial Bus)是連接計算機系統與外部設備的一種串行總線標準,也是一種輸入輸出接口的技術規範,被廣泛地應用於個人電腦和移動設備等信息通信產品。USB總線是最複雜的總線之一,但其廣泛使用。本文首先直接使用USB相關的驅動的應用,後面再具體開始編程做自己的USB驅動程序。
一.USB概要
1.1 USB的發展歷程
USB1.0最早是在1996年出現,速度只有1.5Mb/s,後經多次發展升級,目前使用廣泛的是USB2.0以及USB3.0,最新的USB3.1與USB3.2也在普及中,各版本性能如下表所示:
USB版本 |
出現年代 |
傳輸速度 |
驅動能力 |
USB1.0 |
1996 |
1.5Mbps |
500mA |
USB1.1 |
1998 |
12Mbps |
500mA |
USB2.0 |
2000 |
480Mbps |
500mA |
USB3.0 |
2008 |
5Gbps |
900mA |
USB3.1 |
2013 |
10Gbps |
Type-A 900mA Type-C 100W |
1.2 電氣性能
USB2.0及以下版本採用四線通信,如圖1-1所示:
其中ID數據線沒有畫出,只有在OTG功能中才會使用ID這個信號。USB電纜的4根線在USB接口中有固定不變的數字編號以及不同的顏色,這位電纜的識別和使用提供了方便,下表列出了這些數字和顏色規定。
編號 |
信號 |
電纜顏色 |
1 |
Vbus |
紅色 |
2 |
D- |
白色 |
3 |
D+ |
綠色 |
4 |
GND |
黑色 |
USB3.0向下兼容USB2.0所需要的Vbus,D-,D+和GND四個引腳外,還新增了兩組差分導線,加上一組屏蔽線。新增的雙差分線用於超速數據傳輸,新增的屏蔽線作爲屏蔽線終端,用於處理信號中斷和電子干擾。USB 3.0 Standard-A引腳分配如下:
其中ID數據線沒有畫出,只有在OTG功能中才會使用ID這個信號。USB電纜的4根線在USB接口中有固定不變的數字編號以及不同的顏色,這位電纜的識別和使用提供了方便,下表列出了這些數字和顏色規定。
編號 |
信號 |
電纜顏色 |
1 |
Vbus |
紅色 |
2 |
D- |
白色 |
3 |
D+ |
綠色 |
4 |
GND |
黑色 |
USB3.0向下兼容USB2.0所需要的Vbus,D-,D+和GND四個引腳外,還新增了兩組差分導線,加上一組屏蔽線。新增的雙差分線用於超速數據傳輸,新增的屏蔽線作爲屏蔽線終端,用於處理信號中斷和電子干擾。USB 3.0 Standard-A引腳分配如下:
引腳編號 |
信號 |
描述 |
插合順序 |
1 |
Vbus |
Power |
Second |
2 |
D- |
USB2.0 differential pair |
Third |
3 |
D+ |
||
4 |
GND |
Ground for power return |
Second |
5 |
StdA_SSRX- |
Super speed receiver differential pair |
Last |
6 |
StdA_SSRX+ |
||
7 |
GND_DRAIN |
Ground for signal return |
|
8 |
StdA_SSTX- |
Super speed receiver differential pair |
|
9 |
StdA_SSTX+ |
||
Shell |
Shield |
Connector metal shell |
First |
二. Gadget介紹
Linux-USB Gadget驅動框架實現了USB協議定義的設備端的軟件功能。Gadget框架提出了一套標準API,在底層,USB設備控制器(USB DeviceController,UDC)驅動則實現這一套API,不同的UDC需要不同的驅動,基於API,Gadget驅動實現了一套硬件無關的功能,這基本可以對應到USB協議裏的各種USB Class。
基於底層提供的資源,Gadget驅動可以運行在各種硬件平臺上。重要的驅動有:
Gadget Zero,類似於dummyhcd,該驅動用於測試udc驅動。它會幫助您通過USB-IF測試。
Ethernet over USB,該驅動模擬以太網網口,它支持多種運行方式:
CDC Ethernet: usb規範規定的CommunicationsDevice Class “Ethernet Model” protocol。
CDC Subset:對硬件要求最低的一種方式,主要是 Linux 主機支持該方式。
RNDIS:微軟公司對CDCEthernet的變種實現。
File-backed Storage Gadget最常見的U盤功能實現。
Serial Gadget實現,包括:
Generic Serial實現(只需要Bulk-in/Bulk-out端點+ep0)
CDC ACM規範實現。
Gadget Filesystem,將GadgetAPI接口暴露給應用層,以便在應用層實現user modedriver。
MIDI: 暴露ALSA接口,提供recording以及playback功能。
三. USB虛擬串口
ZYNQ7000中有兩個USB外設,它們都可以當做OTG功能使用,爲了使其變成可以虛擬串口或U盤等USB從設備,需要將USB配置爲從設備。
1.1 配置內核
Linux內核提供了Gadget模塊,該模塊提供了USB的許多通用功能,包括虛擬串口,大容量存儲設備等功能。在內核編譯時配置其爲編譯成模塊。
在內核文件路徑下make menuconfig後,配置選項:
Device Drivers --->
[*]USB support --->
[*]USB Gadget Support --->
[M]USB Gadget Drivers
...
[M]Serial Gadget(with CDC ACM and CDC OBEX support)
保存退出後,編譯內核,在/drivers/usb/gadget目錄下會生成以下驅動文件:
g_serial.ko, libcomposite.ko, usb_f_acm.ko, usb_f_obex.ko, usb_f_serial.ko, u_serial.ko.
配置設備樹,設置USB0爲從設備模式,將原來的dr_mode="host"更改爲:
dr_mode="peripheral":
&usb0 {
status = "okay";
dr_mode = "peripheral";
phy_type = "ulpi";
};
生成新的設備樹devicetree.dtb文件。
1.2 加載模塊並測試
將編譯好的內核,設備樹文件放入SD卡,並啓動Linux,按順序加載前面生成的驅動模塊:
Z-turn# insmod u_serial.ko
Z-turn# insmod libcomposite.ko
Z-turn# insmod usb_f_serial.ko
Z-turn# insmod usb_f_obex.ko
Z-turn# insmod usb_f_acm.ko
Z-turn# insmod g_serial.ko
g_serial gadget: Gadget Serial v2.4
g_serial gadget: g_serial ready
zynq-udc: bind to driver g_serial
Z-turn# g_serial gadget: high-speed config #2: CDC ACM config
g_serial gadget: high-speed config #2: CDC ACM config
輸出上述信息表示加載模塊成功。此時打開設備文件發現多了/dev/ttyGS0設備,這個就是虛擬的串口設備。連接USB數據線到電腦,發現設備管理器中增加了一個串口設備(ELMO GMAS(COM14))。WIN7和WIN10會自動加載基於udc標準的串口驅動,即免驅。
打開串口調試助手,在ZYNQ終端中輸入發送測試命令:
Z-turn# echo hello > /dev/ttyGS0
在串口調試助手中可以收到hello\r\n
在ZYNQ終端輸入串口接收命令:
Z-turn# cat /dev/ttyGS0
在串口調試助手中輸入:hello\n,則ZYNQ終端中可以收到hello。
注:在終端中發送與接收串口數據都是以'\n'爲終止條件,即發送的數據會追加'\n',接收的數據必須在收到'\n'時回顯。
四. USB虛擬U盤
在調試Linux系統時,我們經常需要修改SD卡中的文件,更新文件系統或者Linux內核、設備樹等文件,需要實現通過USB數據線與PC連接,作爲PC的存儲設備,PC可以直接拷貝文件到開發板中,或者把開發板中的文件通過USB數據線拷貝到PC端,實現數據交互。本文辦卡採用Linux3.15內核,ZYNQ7010處理器。
1.1 配置內核
在內核文件路徑下make menuconfig後,配置選項:
Device Drivers --->
[*]USB support --->
[*]USB Gadget Support --->
[M]USB Gadget Drivers
...
[M]Gadget Filesystem
[M]Mass Storage Gadget
編譯內核後,在/drivers/usb/gadget中生成了g_mass_storage.ko文件,把這個文件複製到開發板中。
1.2 PC識別開發板的SD卡
在嵌入式Linux系統中,SD卡在系統中識別爲/dev/mmcblk0,如果有多個分區則每個分區分別是/dev/mmcblk0p1,/dev/mmcblk0p2等,將SD卡目錄掛載到PC中進行讀寫的方法如下:
在終端中執行命令:
Z-turn# modprobe g_mass_storage file=/dev/mmcblk0 removable=1
該命令加載了gadget msc驅動,傳遞SD卡位模塊參數。連接USB數據線到PC,這時在PC端識別了SD卡所有分區,FAT32格式的分區可以顯示內容,對於SD卡的ext4,ext3等文件系統無法在windows中顯示,只顯示一個盤符。此時可以通過USB數據線讀寫SD卡了。
如果只需要掛載一個分區,修改file參數即可:
Z-turn# modprobe g_mass_storage file=/dev/mmcblk0p1 removable=1
1.3 PC識別開發板的內存文件系統(Ramdisk)
首先創建一個50M的內存文件:
Z-turn# dd if=/dev/zero of=/dev/50M bs=1M count=50
加載Gadget相關的模塊:
Z-turn# modprobe g_mass_storage file=/dev/50M removable=1
加載模塊後在windows中彈出是否格式化新增的盤符,格式化爲FAT格式,往該盤符中添加文件,在Linux中將/dev/50M掛載到/mnt目錄下,查看/mnt目錄可以發現添加的文件在其中。
需要注意的是,該文件系統是RAMDISK文件系統,系統重啓後所有的數據內容會丟失。
三. 使用USB共享網絡
使用USB來共享網絡可以不需要連接路由器,減少開發設備。
配置內核:
Device Drivers --->
[*]USB support --->
[*]USB Gadget Support --->
[M]USB Gadget Drivers
...
[M]Ethernet Gadget(with CDC Ethernet support)
[*] RNDIS support
如下圖所示:
還需要配置RNDIS模塊,其位於:
Device Driver--->
Network device support
USB Network Adapters
[*]Multi-purpose USB Networking Framework
<M>HOST for RNDIS and ActiveSync devices
編譯內核後,rndis_hos.ko的路徑爲/drivers/net/usb/rndis_host.ko