參考文章:【正點原子】I.MX6U嵌入式Linux驅(qū)動開發(fā)——Linux USB驅(qū)動
一、簡介
??由于 USB 協(xié)議太過龐大和復(fù)雜,所以本節(jié)只對 STM32MP157 自帶的 USB 驅(qū)動進(jìn)行使能和測試。詳細(xì)的 USB 接口和協(xié)議的介紹,可以參考原子哥的資料《USB2.0 協(xié)議中文版.pdf》和《USB3.0 協(xié)議中文版.pdf》。
??USB 全稱為 Universal Serial Bus,翻譯過來就是通用串行總線,用于規(guī)范電腦與外部設(shè)備的連接與通訊。接口部分,最新的智能手機(jī)均采用 USB Typec 取代了傳統(tǒng)的 3.5mm 耳機(jī)接口,蘋果最新的 MacBook 只有 USB Typec 接口,至于其他的 HDMI、網(wǎng)口等均可以通過 USB Typec 擴(kuò)展塢來擴(kuò)展。協(xié)議部分,USB 目前可以劃分為 USB1.0、USB2.0、USB3.0 以及正在即將到來的 USB4.0。
1.電氣屬性
USB A 插頭一般有四個觸點,也就是 4 根線,從左到右線序依次為 1,2,3,4,第 1 根線為 VBUS,電壓為 5V,第 2 根線為 D-,第 3 根線為 D+,第 4 根線為 GND。USB 采用差分信號來傳輸數(shù)據(jù),因此有 D- 和 D+兩根差分信號線。
Mini USB 插頭一般有五個觸點,第 1 根線為 VCC(5V),第 2 根線為 D-,第 3 根線為 D+,第 4 根線為 ID,第 5 根線為 GND。這個 ID 線用于實現(xiàn) OTG 功能,通過 ID 線來判斷當(dāng)前連接的是主設(shè)備(HOST)還是從設(shè)備(SLAVE)。
2.USB OTG
USB 分為 HOST(主機(jī))和從機(jī)(或 DEVICE),有些設(shè)備可能有時候需要做 HOST,有時候又需要做 DEVICE,USB OTG 應(yīng)運而生,OTG 是 On-The-Go 的縮寫,支持 USB OTG 功能的 USB 接口既可以做 HOST,也可以做 DEVICE。
ID=1:OTG 設(shè)備工作在從機(jī)模式。
ID=0:OTG 設(shè)備工作在主機(jī)模式。
支持 OTG 模式的 USB 接口一般都是 Mini USB、 Micro USB 等這些帶有 ID 線的接口。正點原子的 STM32MP1 開發(fā)板 OTG 模式是使用 USB Type-C 接口,沒有 ID 線。 USB Type C 有自己的識別方法。
3.STM32MP1 USB 接口簡介
STM32MP157 提供了兩個 USB2.0 接口,這兩個 USB 接口都支持高速模式,也就是480Mbit / 秒,都內(nèi)置了高速 PHY。其中 USB2 支持 OTG 功能, 正點原子 STM32MP157 開發(fā)板上的 USB OTG 接口就是連接到 USB2 接口上的。USB1 接口連接了一個 HUB 芯片,可以實現(xiàn) USB Host 接口擴(kuò)展。
4.Type-C 電氣屬性
根據(jù) USB 協(xié)議,USB TypeC 接口也叫做 USB3.1 接口。由于 TypeC 功能比較復(fù)雜,比如支持 PD 充電、顯示、音頻等,這里只關(guān)注 TypeC 的數(shù)據(jù)通信部分。母口的引腳定義如下:
- A1、A12、B1、B12: 這 4 個引腳為 GND
- A2、A3、B2、B3:這 4 個引腳是 USB3.1 特有的,為超高速差分發(fā)送信號線
- A10、A11、B10、B11:這 4 個引腳也是 USB3.1 特有的,為超高速差分接收信號線
- A4、A9、B4、B9: VBUS 引腳
- A5、B5:CC1 和 CC2 這 2 個引腳為 USB3.1 特有的配置通道引腳。Type-C 的插座中有兩個 CC 腳,USB 通信中的角色檢測都是通過 CC 腳進(jìn)行的。對于 TypeC 插頭或者線纜,正常只有一個 CC 引腳,兩個端口連接在一起之后,只存在一個 CC 引腳連接,通過檢測哪一個 CC 有連接,就可以判斷連接的方向。如果USB線纜中有需供電的器件,其中一個CC引腳將作為 VCONN 供電
- A8、B8:SBU1 和 SBU2 引腳,這兩個并不是 USB 信號,而是用作其他功能的,比如 TypeC 作為 DP 接口使用的時候 SBU 用作音頻傳輸通道
- A6、A7、B6、B7:就是 USB2.0 的 D+ 和 D-
標(biāo)準(zhǔn)的Type-C接口是有24個引腳的,也有簡化的16P引腳,去掉了 8 根 USB3.1 高速差分收發(fā)數(shù)據(jù)線。也有6P封裝的接口,與Micro USB的引腳相同,只是換了個接口。
二、USB HOST 驅(qū)動開發(fā)
正點原子的 STM32MP1 開發(fā)板 USB 部分原理圖可以分為兩部分:USB HUB 以及 USB OTG。由于 STM32MP157 芯片只提供了 USB2.0 的接口,所以雖然是 Type-C 接口,本質(zhì)上還是 USB2.0 協(xié)議。另外,使用 TypeC 接口實現(xiàn) OTG 功能需要外接 TypeC 芯片,通過專用的 TypeC 芯片來控制 CC 引腳實現(xiàn) USB 的主從切換。
所以具體的外接芯片需要根據(jù)實際情況選用。
USB HUB原理圖:
使用 FE2.1 這個 HUB 芯片將 STM32MP1 的 USB2 擴(kuò)展成了 7 路 HOST 接口,其中一路供 4G 模塊使用(HUB_DP7/DM7)。注:使用 FE2.1 擴(kuò)展出來的 7 路 USB 接口只能用作 HOST
USB OTG 原理圖:
V1.5版本使用 FUSB302MPX 做控制芯片,在 V1.4 及之前的版本里使用的是 STUSB1600 控制芯片。此控制器主要的功能就是負(fù)責(zé)切換主機(jī)和從機(jī)模式。
I2C1_SCL 和 I2C1_SDA 的引腳分別為:PF14 和 PF15。USB 屬于熱插拔設(shè)備。USB_INT 這個中斷引腳主要是檢測有沒有設(shè)備接入,有設(shè)備接入電平就會被拉低,驅(qū)動進(jìn)入中斷函數(shù),使用 I2C 去讀取寄存器配置開發(fā)板的主從模式,USB_INT 的引腳為 PG2。
FUSB302PMX 版本中,還有一個MT9700HT5,是負(fù)載開關(guān),用來控制 VBUS 輸出。當(dāng) OTG_PWR_CTRL 輸出高電平時 OUT 引腳就輸出 5V 電壓,也就是 VBUS 變?yōu)?5V。當(dāng) OTG_PWR_CTRL 輸出低電平的時候 OUT 輸出 0V,相當(dāng)于 VBUS 關(guān)閉。
所以當(dāng)開發(fā)板上的 TypeC 接口作為主設(shè)備時,OTG_PWR_CTRL 要輸出高電平,VBUS 輸出 5V,為外部 USB 設(shè)備供電。當(dāng) TypeC 接口作為從設(shè)備時,OTG_PWR_CTRL 輸出低電平。OTG_PWR_CTRL 對應(yīng)的 GPIO 引腳為 PZ6。
1.USB HOST 驅(qū)動編寫
USB 子系統(tǒng)是一個標(biāo)準(zhǔn)和復(fù)雜的接口,不過好在 Linux 內(nèi)核已經(jīng)提供了相關(guān)的驅(qū)動,只需要在設(shè)備樹中提供相應(yīng)的節(jié)點即可。
ST 官方的 STM3MP157C-DK2 開發(fā)板已經(jīng)配置好了 USBH 的節(jié)點信息,可以參考此節(jié)點進(jìn)行修改。
在 stm32mp151.dtsi 文件中,可以找到“usbh_ohci”和“usbh_ehci”節(jié)點:
從代碼中可以知道 USBH 是支持 USB2.0 和 USB1.1。使用 USB2.0 就要配置 usbh_ehci 節(jié)點,使用 USB1.1 就要配置 usbh_ohci 節(jié)點。根據(jù) compitable 屬性值,可以查找到驅(qū)動文件為 drivers/usb/host/ohci-platform.c 和 drivers/usb/host/ehciplatform.c。
2.配置 PHY 控制器
同樣在 stm32mp151.dtsi 文件中,可以找到 phy 相關(guān)設(shè)備節(jié)點:
usbphyc 節(jié)點就是 STM32MP1 的 USB PHY,PHY 控制器有兩個端口,對應(yīng)兩個子節(jié)點分別為:usbphyc_port0 和 usbphyc_port1,其中 usbphyc_port0 只能分配給 USB Host?!?phy-cells”屬性值為 0 表示做 OTG 的 PHY 端口,1 表示做 USBH 的 PHY 端口。
將 “stm32mp15xx-dkx.dtsi” 中的 usb_phy_tuning 節(jié)點拷貝到自己的設(shè)備樹中,usb_phy_tuning 此節(jié)點負(fù)責(zé)調(diào)整 PHY 的配置,相關(guān)的參考文檔為 Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml。
usb_phy_tuning: usb-phy-tuning {
st,hs-dc-level = <2>;
st,fs-rftime-tuning;
st,hs-rftime-reduction;
st,hs-current-trim = <15>;
st,hs-impedance-trim = <1>;
st,squelch-level = <3>;
st,hs-rx-offset = <2>;
st,no-lsfs-sc;
};
接著在自己的設(shè)備樹文件中繼續(xù)追加內(nèi)容,用來設(shè)置 usbphyc_port0 節(jié)點。
&usbphyc {
status = "okay";
};
&usbphyc_port0 {
phy-supply = <&v3v3>;
st,phy-tuning = <&usb_phy_tuning>;
};
①將 usbphyc 的 status 屬性修改為“okay”,使能 usbphyc
②給 usbphyc_port0 節(jié)點追加 phy-supply 屬性,添加一個電源管理屬性
③將要修改的 PHY 配置,添加到 usbphyc_port0 節(jié)點里
3.配置usbh_ehci
在自己的設(shè)備樹中,使能 usbh_ehci 和指定 PHY 端口:
&usbh_ehci {
phys = <&usbphyc_port0>;
status = "okay";
};
修改完成后編譯出新的設(shè)備樹,用于啟動開發(fā)板。終端會輸出以下信息:
三、USB HOST 測試
1.鼠標(biāo)鍵盤驅(qū)動使能
在 Linux 內(nèi)核的 menuconfig 中選中以下選項,使能 HID 驅(qū)動:
然后使能 USB 鍵盤和鼠標(biāo)驅(qū)動:
此選項對應(yīng)配置項就是 CONFIG_USB_HID,也就是 USB 接口的 HID 設(shè)備。但是要注意,此驅(qū)動和 HIDBP(Boot Protocol)鍵盤、鼠標(biāo)的驅(qū)動不能一起使用。
然后編譯出新的內(nèi)核鏡像,啟動開發(fā)板。啟動以后插入 USB 鼠標(biāo),會出現(xiàn)以下信息:
并且會在/dev/input 目錄下生成一個名為 eventX(X=0,1,2,3…)的文件,這個就是前面講的輸入子系統(tǒng),鼠標(biāo)和鍵盤都是作為輸入子系統(tǒng)設(shè)備。
如果要測試 USB 鍵盤,可以將 LCD 作為默認(rèn)終端控制臺,在開發(fā)板的 /etc/inittab 中添加以下語句:
tty1::askfirst:-/bin/sh
然后就可以使用開發(fā)板屏幕作為終端控制,使用鍵盤進(jìn)行輸入。
2.U盤驅(qū)動
U 盤使用 SCSI 協(xié)議,所以要先使能 Linux 內(nèi)核中的 SCSI 協(xié)議:
然后使能 USB Mass Storage,也就是 USB 接口的大容量存儲設(shè)備:
然后就可以編譯出內(nèi)核鏡像,啟動開發(fā)板。注:U盤需要格式化為 Fat32 格式,NTFS 和 exFAT 由于版權(quán)問題所以在 Linux 下支持的不完善,可能會出現(xiàn)問題。
例如我的U盤格式化為 NTFS 格式就無法寫入。
成功掛載后,/dev 目錄下會出現(xiàn) sda 和 sda1 兩個文件。/dev/sda 是整個 U 盤,/dev/sda1 是 U 盤的第一個分區(qū),一般使用 U 盤的時候都是只有一個分區(qū)。要想訪問 U 盤需要先對 U 盤進(jìn)行掛載:
mkdir /mnt/usb_disk -p
mount /dev/sda1 /mnt/usb_disk/ -t vfat -o iocharset=utf8
-t 指定掛載所使用的文件系統(tǒng)類型,這里設(shè)置為 vfat,也就是 FAT 文件系統(tǒng),“-o iocharset”設(shè)置硬盤編碼格式為 utf8,否則 U 盤里的中文會顯示亂碼。然后就可以對U盤中的數(shù)據(jù)進(jìn)行讀寫操作了。
卸載U盤:
sync #同步
cd / #退出U盤目錄,否則可能會出現(xiàn)設(shè)備忙狀態(tài),卸載失敗
umount /mnt/usb_disk #卸載
四、USB OTG驅(qū)動開發(fā)
1.USB OTG 控制器節(jié)點信息
在 arch/arm/boot/dts/stm32mp151.dtsi 設(shè)備樹文件中,有一個 usbotg_hs 節(jié)點,此節(jié)點就是 USB OTG 控制器節(jié)點:
根據(jù) compatible 屬性可以找到驅(qū)動文件為 drivers/usb/dwc2/params.c。
2.使能 usbotg_hs 節(jié)點
首先在自己的設(shè)備樹中,配置 PHY 接口,追加 usbphyc_port1 節(jié)點:注:要先使能 usbphyc 節(jié)點
然后追加 usbotg_hs 的相關(guān)屬性信息:
&usbotg_hs {
phys = <&usbphyc_port1 0>;
phy-names = "usb2-phy";
usb-role-switch;
status = "okay";
port {
usbotg_hs_ep: endpoint {
remote-endpoint = <&con_usbotg_hs_ep>;
};
};
};
①配置 usbotg_hs 的 PHY 接口,這里 0 表示為 OTG USB 的 PHY 端口
②把 status 屬性改為 okay,使能 usbotg_hs
③添加了一個 port 節(jié)點,指定 usbotg_hs 節(jié)點使用 con_usbotg_hs_ep 做控制器, con_usbotg_hs_ep 會在 USB 控制芯片對應(yīng)的節(jié)點里創(chuàng)建
電源節(jié)點:
vdd_usb: regulator-vdd-usb {
compatible = "regulator-fixed";
regulator-name = "vdd_usb";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
3.使能 I2C1 節(jié)點
控制 Typec 的芯片是 FUSB302MPX (或 STUSB1600),此芯片是使用 I2C 協(xié)議和 CPU 進(jìn)行通訊,所以要使能 I2C1:
&i2c1 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c1_pins_b>;
pinctrl-1 = <&i2c1_pins_sleep_b>;
status = "okay";
};
4.FUSB302驅(qū)動移植
配置 FUSB302 的中斷電氣屬性,在 stm32mp15-pinctrl.dtsi 中添加以下內(nèi)容:
fusb302_pins_a: fusb302-0 {
pins {
pinmux = <STM32_PINMUX('G', 2, ANALOG)>;
bias-pull-up;
};
};
然后在 stm32mp167d-atk.dts 文件中添加頭文件“dt-bindings/usb/pd.h”。
接著配置 FUSB302 節(jié)點,此節(jié)點為 i2c1 節(jié)點的子節(jié)點:
fusb302@22 {
compatible = "fcs,fusb302","fairchild,fusb302";
reg = <0x22>;
pinctrl-names = "default";
pinctrl-0 = <&fusb302_pins_a>;
int-n-gpios = <&gpiog 2 GPIO_ACTIVE_HIGH>;
vbus-5v-gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>;
status = "okay";
connector {
compatible = "usb-c-connector";
label = "USB-C";
power-role = "dual";
power-opmode = "default";
try-power-role = "sink";
source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
PDO_VAR(3000, 12000, 3000)
PDO_PPS_APDO(3000, 11000, 3000)>;
op-sink-microwatt = <10000000>;
port {
con_usbotg_hs_ep: endpoint {
remote-endpoint = <&usbotg_hs_ep>;
};
};
};
};
①reg 屬性值為“0x22”,表示該芯片的 i2c 通訊地址為0x22
②定義一個 con_usbotg_hs_ep 端口,并指定此端口連接到 usbotg_hs 節(jié)點的 usbotg_hs_ep 端口fusb302 的設(shè)備樹沒有使用電源管理,而是用 PZ6 引腳去控制電壓。此外,Linux 內(nèi)核提供的 fusb302 驅(qū)動不讀取 connector 相關(guān)的屬性,所以不能使用(舊版本代碼,不知道新的有沒有優(yōu)化)。在 github 上有可用的驅(qū)動,或者使用正點原子提供的 fusb302.c 和 fusb302.h,覆蓋掉 drivers/usb/typec/tcpm 目錄下的原驅(qū)動文件。然后再使能內(nèi)核的menuconfig中的相關(guān)配置。
然后編譯出新的內(nèi)核鏡像和設(shè)備樹,啟動開發(fā)板。
五、USB OTG測試
終端打印以下信息,說明加載驅(qū)動成功。
1.模擬U盤(開發(fā)板做從機(jī))
首先配置Linux內(nèi)核,開發(fā)板當(dāng)做一個 U 盤。(選擇編譯成模塊,手動掛載)
然后使用以下命令,編譯內(nèi)核、模塊:
make uImage LOADADDR=0XC2000040 -j32
make modules -j32
編譯完成之后會得到 3 個.ko 內(nèi)核模塊文件:
drivers/usb/gadget/libcomposite.ko
drivers/usb/gadget/function/usb_f_mass_storage.ko
drivers/usb/gadget/legacy/g_mass_storage.ko
將三個文件拷貝到開發(fā)板 /lib/modules/5.4.31 目錄,拷貝完成以后使用新編譯出來的 uImage 啟動開發(fā)板,在開發(fā)板上插入一個 U 盤。記下U盤掛載后的設(shè)備文件名。使用 TypeC 數(shù)據(jù)線將開發(fā)板 OTG 口和電腦連接,連接好以后依次加載 libcomposite.ko、usb_f_mass_storage.ko 和 g_mass_storage.ko 這三個驅(qū)動文件,順序不能錯。
命令如下:
depmod
modprobe libcomposite.ko
modprobe usb_f_mass_storage.ko
modprobe g_mass_storage.ko file=/dev/sda1(設(shè)備文件描述符) removable=1
然后就可以在電腦上對U盤進(jìn)行讀寫操作。
操作完成后使用以下命令退出:
rmmod g_mass_storage.ko
rmmod usb_f_mass_storage.ko
rmmod libcomposite.ko
2.USB聲卡
STM32MP1 開發(fā)板板載了音頻解碼芯片,因此可以將 STM32MP1 開發(fā)板作為一個外置 USB 聲卡,配置 Linux 內(nèi)核:
編譯后會得到以下三個模塊:
drivers/usb/gadget/libcomposite.ko
drivers/usb/gadget/function/usb_f_uac1_legacy.ko
drivers/usb/gadget/legacy/g_audio.ko
然后啟動開發(fā)板,按照之前的教程配置聲卡,保證聲卡正常播音。然后連接 OTG 口和電腦。最后依次加載 libcomposite.ko、usb_f_uac1_legacy.ko 和 g_audio.ko 這三個驅(qū)動模塊:
depmod
modprobe libcomposite.ko
modprobe usb_f_uac1_legacy.ko
modprobe g_audio.ko
加載完成以后稍等一會虛擬出一個 USB 聲卡,打開電腦的設(shè)備管理器,選擇“聲音、視頻和游戲控制器”,會發(fā)現(xiàn)有一個名為“AC Interface”設(shè)備:
將該聲卡作為電腦的揚聲器,就可以使用開發(fā)板放音了:文章來源:http://www.zghlxwxcb.cn/news/detail-413509.html
3.開發(fā)板做OTG主機(jī)
做主機(jī)的話測試方法和上面的 USB HOST 測試一模一樣,直接在正點原子的 USB_OTG 接口上連接一個拓展塢,然后接入鼠標(biāo)鍵盤、U 盤等設(shè)備。文章來源地址http://www.zghlxwxcb.cn/news/detail-413509.html
到了這里,關(guān)于STM32MP157驅(qū)動開發(fā)——USB設(shè)備驅(qū)動的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!