----------------------------------------------------------------------------------------------------------------------------
开发板 :NanoPC-T4
开发板eMMC
:16GB
LPDDR3
:4GB
显示屏 :15.6
英寸HDMI
接口显示屏u-boot
:2023.04
linux
:6.3
----------------------------------------------------------------------------------------------------------------------------
一、设备树
设备树配置参考文档:
- Documentation/devicetree/bindings/usb/generic-ehci.yaml; (
USB
控制器的通用属性配置说明) - Documentation/devicetree/bindings/usb/generic-ohci.yaml; (
USB
控制器的通用属性配置说明) - Documentation/devicetree/bindings/usb/generic-xhci.yaml; (
USB
控制器的通用属性配置说明) - Documentation/devicetree/bindings/usb/fcs,fusb302.yaml;
- Documentation/devicetree/bindings/usb/rockchip,rk3399-dwc3.yaml;(适用于
RK3399
) - Documentation/devicetree/bindings/usb/usb-uhci.txt;
- Documentation/devicetree/bindings/usb/usb-xhci.yaml;
- Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt;
- Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml;
- Documentation/devicetree/bindings/phy/rockchip-usb-phy.yaml;
1.1 USB2.0 Host Type-A
NanoPC-T4
开发板支持两个USB2.0 Host Type-A
接口,对应的USB
控制器为USB2.0 HOST(EHCI&OHCI)
、对应的USB PHY
为USB2.0 HOST PHY
;
因此对应的设备树配置,包括USB2.0 HOST(EHCI&OHCI)
控制器设备树配置和USB2.0 HOST PHY
设备树配置。
1.1.1 控制器配置
(1) USB2.0 HOST0
控制器设备节点usb_host0_ehci
、usb_host0_ohci
定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi
;
usb_host0_ehci: usb@fe380000 {
compatible = "generic-ehci";
reg = <0x0 0xfe380000 0x0 0x20000>;
interrupts = ;
clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
<&u2phy0>;
phys = <&u2phy0_host>;
phy-names = "usb";
status = "disabled";
};
usb_host0_ohci: usb@fe3a0000 {
compatible = "generic-ohci";
reg = <0x0 0xfe3a0000 0x0 0x20000>;
interrupts = ;
clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
<&u2phy0>;
phys = <&u2phy0_host>;
phy-names = "usb";
status = "disabled";
};
在USB
控制器设备节点中,通过phys
属性关联对应的USB PHY
。
phys = <&u2phy0_host>;
这表明这两个USB
控制器都用了u2phy0_host
这个USB PHY
.
这两个USB
控制器就是我们之前介绍的是EHCI
和OHCI
,OHCI
支持USB1.0
和USB1.1
,EHCI
支持USB2.0
。
(2) USB2.0 HOST1
控制器设备节点usb_host1_ehci
、usb_host1_ohci
定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi
;
usb_host1_ehci: usb@fe3c0000 {
compatible = "generic-ehci";
reg = <0x0 0xfe3c0000 0x0 0x20000>;
interrupts = ;
clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>,
<&u2phy1>;
phys = <&u2phy1_host>;
phy-names = "usb";
status = "disabled";
};
usb_host1_ohci: usb@fe3e0000 {
compatible = "generic-ohci";
reg = <0x0 0xfe3e0000 0x0 0x20000>;
interrupts = ;
clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>,
<&u2phy1>;
phys = <&u2phy1_host>;
phy-names = "usb";
status = "disabled";
};
1.1.2 PHY
配置
(1) USB2.0 HOST PHY0
设备节点u2phy0_host
定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi
;
u2phy0: usb2phy@e450 {
compatible = "rockchip,rk3399-usb2phy";
reg = <0xe450 0x10>;
clocks = <&cru SCLK_USB2PHY0_REF>;
clock-names = "phyclk";
#clock-cells = <0>;
clock-output-names = "clk_usbphy0_480m";
status = "disabled";
u2phy0_host: host-port {
#phy-cells = <0>;
interrupts = ;
interrupt-names = "linestate";
status = "disabled";
};
u2phy0_otg: otg-port {
#phy-cells = <0>;
interrupts = ,
,
;
interrupt-names = "otg-bvalid", "otg-id",
"linestate";
status = "disabled";
};
};
(2) USB2.0 HOST PHY1
设备节点u2phy1_host
定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi
;
u2phy1: usb2phy@e460 {
compatible = "rockchip,rk3399-usb2phy";
reg = <0xe460 0x10>;
clocks = <&cru SCLK_USB2PHY1_REF>;
clock-names = "phyclk";
#clock-cells = <0>;
clock-output-names = "clk_usbphy1_480m";
status = "disabled";
u2phy1_host: host-port {
#phy-cells = <0>;
interrupts = ;
interrupt-names = "linestate";
status = "disabled";
};
u2phy1_otg: otg-port {
#phy-cells = <0>;
interrupts = ,
,
;
interrupt-names = "otg-bvalid", "otg-id",
"linestate";
status = "disabled";
};
};
1.1.3 电源配置
(1) USB2.0 PHY
芯片三路电源依次为VCCA0V9_S3
、VCCA1V8_S3
、VCC3V3_S3
;
VCCA0V9_S3
、VCCA1V8_S3
这两路由PMIC_SLEEP_H
(连接RK3399
的GPIO1_A5/AP_PWROFF
,这个应该是处理的睡眠引脚,处理器工作时电源有效)引脚控制的;
VCC3V3_S3
由RK808
电源管理芯片第7号引脚VSWOUT
提供,因此需要配置其电源输出为3.3V
;
在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
配置vcc3v3_s3
设备节点;
&i2c0 {
......
rk808: pmic@1b {
......
regulators {
......
vcc3v3_s3: SWITCH_REG1 {
regulator-always-on;
regulator-boot-on;
regulator-name = "vcc3v3_s3";
regulator-state-mem {
regulator-off-in-suspend;
};
};
......
};
};
};
完整的rk808
设备节点配置参考:rk808
驱动配置。
(2) USB2.0 Host Type-A
接口电源VCC5V0_HOST0
由RT9724GQW
提供的,其输入端为VCC5V0_SYS
。
在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
配置vcc5v0_host
;
vcc5v0_sys: vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
vcc5v0_host: vcc5v0-host-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
regulator-always-on;
regulator-boot-on;
vin-supply = <&vcc5v0_sys>;
};
1.1.4 使能
下面介绍的都是配置在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
文件。
(1) 为了同时支持USB1.0
、USB1.1
和USB2.0
,就需要同时用到EHCI
和OHCI
,因此需要把这两个USB
控制器都打开:
&usb_host0_ehci {
status = "okay";
};
&usb_host0_ohci {
status = "okay";
};
&usb_host1_ehci {
status = "okay";
};
&usb_host1_ohci {
status = "okay";
};
(2) 使能USB2.0 HOST PHY0
,同时配置USB2.0 HOST PHY0 phy-supply
属性,用于控制USB
电源VBUS
;
&u2phy0 {
status = "okay";
};
&u2phy0_host {
phy-supply = <&vcc5v0_host>;
status = "okay";
};
(3) 使能USB2.0 HOST PHY1
,同时配置USB2.0 HOST PHY1 phy-supply
属性,用于控制USB
电源VBUS
;
&u2phy1 {
status = "okay";
};
&u2phy1_host {
phy-supply = <&vcc5v0_host>;
status = "okay";
};
1.2 USB3.0 Host Type-A
NanoPC-T4
开发板支持1个USB3.0 Host Type-A
接口,对应的USB
控制器为USB3.0/2.0 OTG1(DWC3/xHCI)
、对应的USB PHY
为USB3.0 Type-C PHY1
和USB2.0 OTG PHY1
;
因此对应的设备树配置,包括USB3.0/2.0 OTG1(DWC3/xHCI)
控制器设备树配置和USB3.0 Type-C PHY1
、USB2.0 OTG PHY1
设备树配置。
1.2.1 控制器配置
(1) USB3.0/2.0 OTG1(DWC3/xHCI)
控制器设备节点usbdrd3_1
,定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi
;
usbdrd3_1: usb@fe900000 {
compatible = "rockchip,rk3399-dwc3";
#address-cells = <2>;
#size-cells = <2>;
ranges;
clocks = <&cru SCLK_USB3OTG1_REF>, <&cru SCLK_USB3OTG1_SUSPEND>,
<&cru ACLK_USB3OTG1>, <&cru ACLK_USB3_RKSOC_AXI_PERF>,
<&cru ACLK_USB3>, <&cru ACLK_USB3_GRF>;
clock-names = "ref_clk", "suspend_clk",
"bus_clk", "aclk_usb3_rksoc_axi_perf",
"aclk_usb3", "grf_clk";
resets = <&cru SRST_A_USB3_OTG1>;
reset-names = "usb3-otg";
status = "disabled";
usbdrd_dwc3_1: usb@fe900000 {
compatible = "snps,dwc3";
reg = <0x0 0xfe900000 0x0 0x100000>;
interrupts = ;
clocks = <&cru SCLK_USB3OTG1_REF>, <&cru ACLK_USB3OTG1>,
<&cru SCLK_USB3OTG1_SUSPEND>;
clock-names = "ref", "bus_early", "suspend";
dr_mode = "otg";
phys = <&u2phy1_otg>, <&tcphy1_usb3>;
phy-names = "usb2-phy", "usb3-phy";
phy_type = "utmi_wide";
snps,dis_enblslpm_quirk;
snps,dis-u2-freeclk-exists-quirk;
snps,dis_u2_susphy_quirk;
snps,dis-del-phy-power-chg-quirk;
snps,dis-tx-ipgap-linecheck-quirk;
power-domains = <&power RK3399_PD_USB3>;
status = "disabled";
};
};
1.2.2 PHY
配置
(1) USB3.0 Type-C PHY1
设备节点tcphy1_usb3
,定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi
;
tcphy1: phy@ff800000 {
compatible = "rockchip,rk3399-typec-phy";
reg = <0x0 0xff800000 0x0 0x40000>;
clocks = <&cru SCLK_UPHY1_TCPDCORE>,
<&cru SCLK_UPHY1_TCPDPHY_REF>;
clock-names = "tcpdcore", "tcpdphy-ref";
assigned-clocks = <&cru SCLK_UPHY1_TCPDCORE>;
assigned-clock-rates = <50000000>;
power-domains = <&power RK3399_PD_TCPD1>;
resets = <&cru SRST_UPHY1>,
<&cru SRST_UPHY1_PIPE_L00>,
<&cru SRST_P_UPHY1_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
rockchip,grf = <&grf>;
status = "disabled";
tcphy1_dp: dp-port {
#phy-cells = <0>;
};
tcphy1_usb3: usb3-port {
#phy-cells = <0>;
};
};
(2) USB2.0 OTG PHY1
设备节点u2phy1_otg
,定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi
;
u2phy1: usb2phy@e460 {
compatible = "rockchip,rk3399-usb2phy";
reg = <0xe460 0x10>;
clocks = <&cru SCLK_USB2PHY1_REF>;
clock-names = "phyclk";
#clock-cells = <0>;
clock-output-names = "clk_usbphy1_480m";
status = "disabled";
u2phy1_host: host-port {
#phy-cells = <0>;
interrupts = ;
interrupt-names = "linestate";
status = "disabled";
};
u2phy1_otg: otg-port {
#phy-cells = <0>;
interrupts = ,
,
;
interrupt-names = "otg-bvalid", "otg-id",
"linestate";
status = "disabled";
};
};
1.2.3 电源配置
(1) USB2.0 PHY1
芯片三路电源依次为VCCA0V9_S3
、VCCA1V8_S3
、VCC3V3_S3
, 这个配置上面已经介绍了,不再重复介绍。
(2) USB3.0 Type-C PHY1
芯片三路电源和USB2.0 PHY1
芯片三路电源一样。
(3) USB3.0 Host Type-A
接口电源VCC5V0_HOST2
由RT9724GQW
提供的,其输入端为VCC5V0_SYS
。
在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
配置vcc5v2_host
;
vcc5v0_sys: vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
vcc5v2_host: vcc5v2-host-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc5v2_host";
regulator-always-on;
regulator-boot-on;
vin-supply = <&vcc5v0_sys>;
};
1.2.4 使能
下面介绍的都是配置在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
文件。
(1) 使能usbdrd3_1
:
/* Configurate and Enable USB3.0/2.0 OTG Controller */
&usbdrd3_1 {
status = "okay";
};
&usbdrd_dwc3_1 {
/* 配置dr_mode为host,表示只支持Host only mode */
dr_mode = "host";
status = "okay";
};
(2) 使能tcphy1_usb3
;
/* Enable USB3.0 PHY */
&tcphy1 {
status = "okay";
};
&tcphy1_usb3{
status = "okay";
};
(3) 使能u2phy1_otg
,同时配置USB2.0 OTG PHY1 phy-supply
属性,用于控制USB
电源VBUS
;
/* Enable USB2.0 PHY */
&u2phy1 {
status = "okay";
};
&u2phy1_otg {
phy-supply = <&vcc5v2_host>;
status = "okay";
};
1.2.5 总结
USB3.0 Host Type-A
接口设备树配置的注意点如下:
- 对应的
fusb
节点不要配置,因为USB3.0 Host Type-A
接口不需要fusb302
芯片; - 对应的
USB
控制器子节点(usbdrd_dwc3
)和PHY
的节点(tcphy
和u2phy
)都要删除extcon
属性; - 对应的
USB
控制器子节点(usbdrd_dwc3
)的dr_mode
属性要配置为host
;
1.3 USB3.0 Type-C
NanoPC-T4
开发板支持1个USB3.0 Type-C
接口,对应的USB
控制器为USB3.0/2.0 OTG0(DWC3/xHCI)
、对应的USB PHY
为USB3.0 Type-C PHY0
和USB2.0 OTG PHY0
;
因此对应的设备树配置,包括USB3.0/2.0 OTG0(DWC3/xHCI)
控制器设备树配置和USB3.0 Type-C PHY0
、USB2.0 OTG PHY0
设备树配置。
1.3.1 控制器配置
(1) USB3.0/2.0 OTG0(DWC3/xHCI)
控制器设备节点usbdrd3_0
,定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi
;
usbdrd3_0: usb@fe800000 {
compatible = "rockchip,rk3399-dwc3";
#address-cells = <2>;
#size-cells = <2>;
ranges;
clocks = <&cru SCLK_USB3OTG0_REF>, <&cru SCLK_USB3OTG0_SUSPEND>,
<&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_RKSOC_AXI_PERF>,
<&cru ACLK_USB3>, <&cru ACLK_USB3_GRF>;
clock-names = "ref_clk", "suspend_clk",
"bus_clk", "aclk_usb3_rksoc_axi_perf",
"aclk_usb3", "grf_clk";
resets = <&cru SRST_A_USB3_OTG0>;
reset-names = "usb3-otg";
status = "disabled";
usbdrd_dwc3_0: usb@fe800000 {
compatible = "snps,dwc3";
reg = <0x0 0xfe800000 0x0 0x100000>;
interrupts = ;
clocks = <&cru SCLK_USB3OTG0_REF>, <&cru ACLK_USB3OTG0>,
<&cru SCLK_USB3OTG0_SUSPEND>;
clock-names = "ref", "bus_early", "suspend";
dr_mode = "otg";
phys = <&u2phy0_otg>, <&tcphy0_usb3>;
phy-names = "usb2-phy", "usb3-phy";
phy_type = "utmi_wide";
snps,dis_enblslpm_quirk;
snps,dis-u2-freeclk-exists-quirk;
snps,dis_u2_susphy_quirk;
snps,dis-del-phy-power-chg-quirk;
snps,dis-tx-ipgap-linecheck-quirk;
power-domains = <&power RK3399_PD_USB3>;
status = "disabled";
};
};
1.3.2 PHY
配置
(1) USB3.0 Type-C PHY0
设备节点tcphy0_usb3
,定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi
;
tcphy0: phy@ff7c0000 {
compatible = "rockchip,rk3399-typec-phy";
reg = <0x0 0xff7c0000 0x0 0x40000>;
clocks = <&cru SCLK_UPHY0_TCPDCORE>,
<&cru SCLK_UPHY0_TCPDPHY_REF>;
clock-names = "tcpdcore", "tcpdphy-ref";
assigned-clocks = <&cru SCLK_UPHY0_TCPDCORE>;
assigned-clock-rates = <50000000>;
power-domains = <&power RK3399_PD_TCPD0>;
resets = <&cru SRST_UPHY0>,
<&cru SRST_UPHY0_PIPE_L00>,
<&cru SRST_P_UPHY0_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
rockchip,grf = <&grf>;
status = "disabled";
tcphy0_dp: dp-port {
#phy-cells = <0>;
};
tcphy0_usb3: usb3-port {
#phy-cells = <0>;
};
};
(2) USB2.0 OTG PHY0
设备节点u2phy0_otg
,定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi
;
u2phy0: usb2phy@e450 {
compatible = "rockchip,rk3399-usb2phy";
reg = <0xe450 0x10>;
clocks = <&cru SCLK_USB2PHY0_REF>;
clock-names = "phyclk";
#clock-cells = <0>;
clock-output-names = "clk_usbphy0_480m";
status = "disabled";
u2phy0_host: host-port {
#phy-cells = <0>;
interrupts = ;
interrupt-names = "linestate";
status = "disabled";
};
u2phy0_otg: otg-port {
#phy-cells = <0>;
interrupts = ,
,
;
interrupt-names = "otg-bvalid", "otg-id",
"linestate";
status = "disabled";
};
};
1.3.3 电源配置
(1) USB2.0 PHY0
芯片三路电源依次为VCCA0V9_S3
、VCCA1V8_S3
、VCC3V3_S3
, 这个配置上面已经介绍了,不再重复介绍。
(2) USB3.0 Type-C PHY0
芯片三路电源和USB2.0 PHY0
芯片三路电源一样。
(3) USB3.0 Type-C
接口电源VBUS_TYPEC
由RT9724GQW
提供的,其输入端为VCC5V0_SYS
。由GPIO4_D2
引脚使能,高电平有效;
在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
配置vbus_typec
;
vcc5v0_sys: vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
vbus_typec: vbus-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&vbus_typec_en>;
regulator-name = "vbus_typec";
vin-supply = <&vcc5v0_sys>;
};
由于vbus_typec
节点配置了default
状态对应的引脚配置节点为vbus_typec_en
,因此需要在pinctrl
节点下增加引脚配置节点vbus_typec_en
,这个节点在fusb
配置中介绍。
1.3.4 fusb302
配置
在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
配置:
&i2c4 {
clock-frequency = <400000>;
i2c-scl-rising-time-ns = <160>;
i2c-scl-falling-time-ns = <30>;
status = "okay";
fusb0: typec-portc@22 {
compatible = "fcs,fusb302";
reg = <0x22>;
interrupt-parent = <&gpio1>;
interrupts = ;
pinctrl-names = "default";
pinctrl-0 = <&fusb0_int>;
vbus-supply = <&vbus_typec>;
status = "okay";
};
};
&pinctrl {
fusb30x {
fusb0_int: fusb0-int {
rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;
};
vbus_typec_en: vbus-typec-en {
rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
......
}
其中GPIO1_A2
连接了fusb302
的中断引脚,低电平触发。
fusb0
设备节点匹配的驱动程序是drivers/usb/typec/tcpm/fusb302.c
。
如果你使用的是linux 4.19
,更改设备节点fusb0
如下:
&i2c4 {
.....
fusb0: fusb30x@22 {
compatible = "fairchild,fusb302";
reg = <0x22>;
pinctrl-names = "default";
pinctrl-0 = <&fusb0_int>;
int-n-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; /* 中断引脚GPIO1_A2配置 */
vbus-5v-gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>; /* VBUS使能引脚GPIO4_D2配置 */
status = "okay";
};
};
fusb0
设备节点匹配的驱动程序是drivers/mfd/fusb302.c
。
1.3.5 使能
下面介绍的都是配置在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
文件。
(1) 使能usbdrd3_0
:
通过dr_mode
属性设置USB
控制器的模式,一共有三种模式:otg
(同时支持主机/设备)、host
(主机)、peripheral
(设备);这里配置为otg
;
/* Configurate and Enable USB3.0/2.0 OTG Controller notifier */
&usbdrd3_0 {
status = "okay";
};
&usbdrd_dwc3_0 {
/* 配置dr_mode为otg */
dr_mode = "otg";
status = "okay";
};
需要注意的是由于我们使用的是linux 6.3
内核,内核没有支持驱动drivers/mfd/fusb302.c
,导致不会为fusb302
驱动注册extcon
设备,因此不要在usbdrd3_0
设备节点配置extcon
属性,不然将会由于找不到extcon
,导致usbdrd3_0
无法正常工作;并且出现类似如下错误:
[ 24.692156] platform ff7c0000.phy: deferred probe pending
[ 24.692188] platform fe800000.usb: deferred probe pending
如果你使用的是linux 4.19
的内核,由于内核支持驱动drivers/mfd/fusb302.c
,因此在usbdrd3_0
节点配置extcon
属性;
&usbdrd3_0 {
status = "okay";
/* 配置extcon属性,用于接收fusb302驱动的UFP/DFP */
extcon = <&fusb0>;
};
(2) 使能tcphy0_usb3
;
/* Enable USB3.0 PHY */
&tcphy0 {
status = "okay";
};
&tcphy0_usb3{
status = "okay";
};
同上,如果是linux 4.19
的内核,需要在tcphy0
节点配置extcon
属性。
(3) 使能u2phy0_otg
,同时配置USB2.0 OTG PHY0 phy-supply
属性,用于控制USB
电源VBUS
;
/* Enable USB2.0 PHY */
&u2phy0 {
status = "okay";
};
&u2phy0_otg {
phy-supply = <&vbus_typec>;
status = "okay";
};
同上,如果是linux 4.19
的内核,需要在u2phy0
节点配置extcon
属性。
1.3.6 总结
USB3.0 Type-C
设备树配置的注意点如下:
- 对应的
fusb
节点需要配置,因为USB3.0 Type-C
需要fusb302
芯片; - 对应的
USB
控制器子节点(usbdrd_dwc3
)和PHY
的节点(tcphy
和u2phy
)都要配置extcon
属性; - 对应的
USB
控制器子节点(usbdrd_dwc3
)的dr_mode
属性要配置为otg
;
二、 配置内核
2.1 配置USB PHY
在linux
内核根目录下执行make menuconfig
配置以下选项:
Device Drivers --->
PHY Subsystem --->
<*> Rockchip INNO USB2PHY Driver
<*> Rockchip TYPEC PHY Driver
USB2.0 PHY
使用的是Innosilicon IP
,所以应选择Rockchip INNO USB2PHY Driver
,驱动位于drivers/phy/rockchip/phy-rockchip-inno-usb2.c
;USB3.0 Type-C PHY
使用的是Type-C
,所以应选择Rockchip TYPEC PHY Driver
,驱动位于drivers/phy/rockchip/phy-rockchip-typec.c
;
2.2 配置USB
控制器
在linux
内核根目录下执行make menuconfig
配置以下选项:
Device Drivers --->
[*] USB support --->
<*> xHCI HCD (USB 3.0) support
-*- Generic xHCI driver for a platform device
<*> EHCI HCD (USB 2.0) support
-*- Root Hub Transaction Translators
[*] Improved Transaction Translator scheduling
<*> Generic EHCI driver for a platform device
<*> OHCI HCD (USB 1.1) support
<*> Generic OHCI driver for a platform device
<*> USB support -->
[*] USB announce new devices(输出识别的每个usb设备的基本信息,比如idVendor、idProduct、制造商、产品、和序列号等)
OHCI HCD (USB 1.1)
选择OHCI Driver
配置;
EHCI HCD (USB 2.0)
选择EHCI Driver
配置;
xHCI HCD (USB 3.0)
选择xHCI Driver
配置。
2.3 配置USB OTG
默认情况下dw3
是双角色(即同时支持Host
和Device
模式,可以动态切换):
Device Drivers --->
[*] USB support --->
<*> DesignWare USB2 DRD Core Support
DWC2 Mode Selection (Dual Role mode)
<*> DesignWare USB3 DRD Core Support
DWC3 Mode Selection (Dual Role mode)
RK3399 USB3.0 OTG
使用Synopsys
方案,即xHCI
扩展的DWC3
控制器,因此需要配置DesignWare USB3 DRD Core Support
。
2.4 配置USB Gadget
由于我们将USB3.0 Type-C
接口配置为了USB OTG
,作为USB device
(丛机)使用,因此我们可以将开发板模拟成一个存储设备、或者声卡、鼠标等设备,然后可以通过开发板上的USB3.0 Type-C
接口将PC
和开发板连接在一起。
在linux
内核根目录下执行make menuconfig
配置以下选项:
Device Drivers --->
[*] USB support --->
<*> USB Gadget Support --->
USB Gadget functions configurable through configfs
[*] Generic serial bulk in/out
[*] Abstract Control Model (CDC ACM)
[*] Object Exchange Model (CDC OBEX)
[*] Network Control Model (CDC NCM)
[*] Ethernet Control Model (CDC ECM)
[*] Ethernet Control Model (CDC ECM) subset
[*] RNDIS
[*] Ethernet Emulation Model (EEM)
[*] Mass storage (大容量存储功能)
[ ] Loopback and sourcesink function (for testing)
[*] Function filesystem (FunctionFS)
[*] Audio Class 1.0 (音频功能 1.0)
[*] Audio Class 1.0 (legacy implementation)
[*] Audio Class 2.0 (音频功能 2.0)
[ ] MIDI function
[*] HID function (HID功能)
[*] USB Webcam functio (USB摄像头功能)
[ ] Printer function
USB Gadget precomposed configurations --->
Audio Gadget (音频设备)
< > Ethernet Gadget (with CDC Ethernet support) (网络设备)
< > Network Control Model (NCM) support
<*> Gadget Filesystem
<*> Function Filesystem
Mass Storage Gadget (存储设备)
< > Serial Gadget (with CDC ACM and CDC OBEX support) (串口设备)
< > MIDI Gadget
< > Printer Gadget (打印机)
< > CDC Composite Device (Ethernet and ACM)
< > CDC Composite Device (ACM and mass storage)
< > Multifunction Composite Gadget
HID Gadget (hid设备)
< > EHCI Debug Device Gadget
< > USB Webcam Gadget (`USB`摄像头)
< > USB Raw Gadget
USB Gadget
驱动主要包括两大块:
-
USB Gadget functions
:各种USB
子类设备功能驱动,位于drivers/usb/gadget/function
目录下,里面给出了对应的sample
。其作用是配置USB
子类协议的接口描述以及其它子类协议,比如uvc
协议,hid
等; -
USB Gadget Legacy
:整个Gadget
设备驱动的入口,位于drivers/usb/gadget/legacy
目录下:里面给出了常用的USB
类设备的驱动sample
。其作用就是配置USB
设备描述符信息,提供一个usb_composite_driver
, 然后注册到composite
层。
有关USB Gadget
驱动更加具体内容参考《一文搞懂 USB
设备端驱动框架》。
下面我们介绍几个Gadget
设备驱动:
Mass Storage Gadget
用于模拟大容量存储设备;需要注意:linux
下的SD
卡、eMMC
文件系统一般是ext4
,在windows
下不识别;所以如果做实验,可以使用FAT
格式的存储器,比如U
盘;或者是NFTS
格式的移动硬盘;因此我们还需要配置内核支持exFAT
/NFTS
文件系统;
File systems
<*> FUSE (Filesystem in Userspace) support
DOS/FAT/EXFAT/NT Filesystems --->
< > MSDOS fs support
<*> VFAT (Windows-95) fs support
(437) Default codepage for FAT
(iso8859-1) Default iocharset for FAT
[*] Enable FAT UTF-8 option by default
<*> exFAT filesystem support
(utf8) Default iocharset for exFAT (NEW)
<*> NTFS file system support
[ ] NTFS debugging support
[*] NTFS write support
<*> NTFS Read-Write file system support
[*] 64 bits per NTFS clusters
[*] activate support of external compressions lzx/xpress
[*] NTFS POSIX Access Control Lists
-
Audio Gadget
用于模拟声卡;USB
声卡就是USB
接口的外置声卡,一般电脑都自带了声卡,但是内部自带的声卡效果相对来说比较差,不能满足很多HIFI
玩家的需求,USB
声卡通过USB
接口来传递音频数据。具体的ADC
和DAC
过程由声卡完成,摆脱了电脑主板体积的限制,外置USB
声卡就可以做的很好。NanoPC-T4
开发板搭载了音频解码芯片,因此可以将NanoPC-T4
开发板作为一个外置USB
声卡。该驱动程序它会自动使用默认音频解码器来播放来自主机机器的音频。 -
HID Gadget
用于模拟人机接口设备,包括键盘、鼠标、操纵杆、扫描仪、数字化板、触摸屏等。
此外我们还配置了Gadget Filesystem
和Function Filesystem
;
Gadget Filesystem
:Gadget
文件系统是通过/config/usb_gadget/
目录暴露给用户空间的一个虚拟文件系统。在该文件系统下,可以创建和配置USB gadget
设备。例如,可以创建用于描述设备信息和字符串描述符的文件、定义功能的文件,并通过对这些文件进行操作来配置USB gadget
;Function Filesystem
:Function
文件系统是一个以/sys/class/udc/
为根目录的伪文件系统。它通过与USB
控制器驱动程序进行交互,用于配置和管理USB gadget
功能。在该文件系统中,每个USB gadget
功能都表示为一个子目录,可以在其中配置各种功能参数。例如,对于Mass Storage
功能,可以在/sys/class/udc/gadget_name/function_name/
目录下找到相关配置文件。
2.5 配置USB
外设
根据开发板硬件情况,配置支持各种USB
设备。
2.51 配置大容量存储设备
移动硬盘属于SCSI
设备,所以在配置USB
模块之前需要配置SCSI
选项;
Device Drivers --->
SCSI device support --->
<*> SCSI device support
[*] legacy /proc/scsi/ support
*** SCSI support type (disk, tape, CD-ROM) ***
<*> SCSI disk support
< > SCSI tape support
< > SCSI CDROM support
<*> SCSI generic support
[*] /dev/bsg support (SG v4)
<*> SCSI media changer support
[*] Verbose SCSI error reporting (kernel size +=75K)
[*] SCSI logging facility
[*] Asynchronous SCSI scanning
SCSI Transports --->
[*] SCSI low-level drivers --->
[ ] SCSI Device Handlers ----
配置完SCSI Device Support
后,可以在USB Support
中找到如下选项,选上即可
Device Driver --->
[*] USB support --->
<*> USB Mass Storage support
2.5.2 配置USB
转串口
(1) 支持USB 3G Modem
USB 3G Modem
使用的是USB
转串口,使用时需要选上如下选项:
Device Driver --->
[*] USB support --->
<*> USB Serial Converter support --->
<*> USB driver for GSM and CDMA modems
此外,USB 3G Modem
还需要使能PPP
拨号的相关配置项:
Device Driver --->
[*] Network device support --->
<*> PPP (point-to-point protocol) support
<*> PPP BSD-Compress compression
<*> PPP Deflate compression
[*] PPP filtering
<*> PPP MPPE compression (encryption)
[*] PPP multilink support
<*> PPP over Ethernet
<*> PPP over L2TP
<*> PPP on L2TP Access Concentrator
<*> PPP on PPTP Network Server
<*> PPP support for async serial ports
<*> PPP support for sync tty ports
(2) 支持PL2303
如果要使用PL2303
输出数据到串口,需要选择如下选项,同时需要禁用 USB driver for GSM and CDMA modems
,否则,PL2303
可能会被误识别为USB 3G modem
;
Device Driver --->
[*] USB support --->
<*> USB Serial Converter support --->
<*> USB Prolific 2303 Single Port Serial Driver
(3) 支持USB GPS
如果要支持USB GPS
,如u-blox 6-GPS Receiver
设备,需要选择如下选项:
Device Drivers --->
[*] USB support --->
[*] USB Modem (CDC ACM) support
2.5.3 配置HID
USB
键盘、鼠标、触摸屏的配置选项如下:
Device Drivers --->
[*] HID bus support
-*- HID bus core support
<*> Generic HID driver
USB HID support --->
<*> USB HID transport layer
[ ] PID device support
[*] /dev/hiddev raw HID device support
USB HID transport layer
(USB
人机接口设备传输层) 此选项对应配置项就是CONFIG_USB_HID
,也就是USB
接口的HID
设备。如果要使用USB
接口的keyboards
(键盘)、mice
(鼠标)、joysticks
(摇杆)、graphic tablets
(绘图板)等其他的HID
设备,那么就需要选中USB HID Transport layer
。
USB HID Transport Layer
是USB
协议栈中的一个组件,用于支持 HID
类型的设备与计算机之间的通信。USB HID
传输层负责解析来自HID
设备的数据,并将其转换为适当的格式,以便应用程序可以理解和使用。
关于USB
鼠标我们之前有单独的文章介绍:linux
驱动移植-usb
鼠标接口驱动。
关于USB
键盘我们之前有单独的文章介绍:linux
驱动移植-usb
键盘接口驱动。
实际上在linux
中还有一个通用输入层子系统,用于处理和管理各种输入设备,例如键盘、鼠标、触摸屏和游戏手柄等。通用输入层提供了一个统一的接口,使应用程序可以以一致的方式与不同类型的输入设备进行交互,配置如下:
Device Drivers --->
Input device support
-*- Generic input layer (needed for keyboard, mouse, ...)
那他们之间有什么区别呢?
区别在于,Generic Input Layer
是Linux
内核的一个通用输入设备管理层,它与各种输入设备进行交互,并将输入数据传递给应用程序。USB HID Transport Layer
则 USB
协议栈中的一个特定组件,专门用于处理HID
设备的通信和数据传输。通用输入层可以与各种输入设备一起使用(不仅限于USB HID
设备),而USB HID
传输层则专注于USB HID
设备的通信协议。
针对于USB
输入设备,我们配置USB HID transport layer
即可。
2.5.4 配置USB
摄像头
Device Drivers -->
--- Multimedia support
[ ] Filter media drivers (取消选择)
Media core support --->
<*> Video4Linux core (NEW)
[*] Media Controller API (NEW)
Media drivers --->
[*] Media USB Adapters(启用usb总线的媒体驱动程序,drivers/media/usb)
<*> USB Video Class(UVC)(我们的摄像头支持UVC,选择这个驱动即可)
[*] UVC input events device supports(NEW)
<> GSPCA based webcams --> (GSPCA 是一个法国程序员在业余时间制作的一个万能USB 摄像头驱动程序,在此可以选择对应类型USB摄像头的支持)
<> SONIX Bayer USB Camer Driver (NEW)
<> OV772x/OV965x/... 系列摄像头支持
<> ....
[*] Media platform devices (NEW) --->
[*]V4L platform devices
关于USB
摄像头我们之前有单独的文章介绍:linux
驱动移植-usb
摄像头uvc
驱动。
2.5.5 配置USB
音频
Device Driver --->
<*> Sound card support --->
<*> Advanced Linux Sound Architecture --->
[*] USB sound devices --->
[*] USB Audio/MIDI driver
2.5.6 配置USB HUB
如果要支持USB HUB
,请将Disable external hubs
配置选项去掉;
Device Drivers --->
[*] USB support --->
[ ] Disable external hubs
其它有可能用到的USB
设备还有很多,如GPS
,Printer
等,有可能需要Vendor
定制的驱动,也有可能
是标准的 设备类驱动,如需支持这类设备,可直接在网络上搜索linux
对该设备支持要做的工作。
2.6 配置extcon
2.6.1 linux 6.3
配置
配置Fairchild FUSB302 Type-C chip driver
驱动,将drivers/usb/typec/tcpm/fusb302.c
编译到内核;
Device Driver --->
-*- External Connector Class (extcon) support --->
<*> USB support --->
<*> USB Type-C Support --->
[*] USB Type-C Port Controller Manager --->
[*] Fairchild FUSB302 Type-C chip driver
需要注意的是drivers/usb/typec/tcpm/fusb302.c
驱动并不会注册extcon
设备;因此无法识别是接入了USB
主机或USB
设备。
drivers/usb/typec/tcpm/fusb302.c
的probe
函数:
static int fusb302_probe(struct i2c_client *client)
{
struct fusb302_chip *chip;
struct i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev;
const char *name;
int ret = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
dev_err(&client->dev,
"I2C/SMBus block functionality not supported!\n");
return -ENODEV;
}
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
chip->i2c_client = client;
chip->dev = &client->dev;
mutex_init(&chip->lock);
/*
* Devicetree platforms should get extcon via phandle (not yet
* supported). On ACPI platforms, we get the name from a device prop.
* This device prop is for kernel internal use only and is expected
* to be set by the platform code which also registers the i2c client
* for the fusb302.
*/
if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {
chip->extcon = extcon_get_extcon_dev(name);
if (IS_ERR(chip->extcon))
return PTR_ERR(chip->extcon);
}
chip->vbus = devm_regulator_get(chip->dev, "vbus");
if (IS_ERR(chip->vbus))
return PTR_ERR(chip->vbus);
chip->wq = create_singlethread_workqueue(dev_name(chip->dev));
if (!chip->wq)
return -ENOMEM;
spin_lock_init(&chip->irq_lock);
INIT_WORK(&chip->irq_work, fusb302_irq_work);
INIT_DELAYED_WORK(&chip->bc_lvl_handler, fusb302_bc_lvl_handler_work);
init_tcpc_dev(&chip->tcpc_dev);
fusb302_debugfs_init(chip);
if (client->irq) {
chip->gpio_int_n_irq = client->irq;
} else {
ret = init_gpio(chip);
if (ret < 0)
goto destroy_workqueue;
}
chip->tcpc_dev.fwnode = fusb302_fwnode_get(dev);
if (IS_ERR(chip->tcpc_dev.fwnode)) {
ret = PTR_ERR(chip->tcpc_dev.fwnode);
goto destroy_workqueue;
}
chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev);
if (IS_ERR(chip->tcpm_port)) {
fwnode_handle_put(chip->tcpc_dev.fwnode);
ret = dev_err_probe(dev, PTR_ERR(chip->tcpm_port),
"cannot register tcpm port\n");
goto destroy_workqueue;
}
ret = request_irq(chip->gpio_int_n_irq, fusb302_irq_intn,
IRQF_ONESHOT | IRQF_TRIGGER_LOW,
"fsc_interrupt_int_n", chip);
if (ret < 0) {
dev_err(dev, "cannot request IRQ for GPIO Int_N, ret=%d", ret);
goto tcpm_unregister_port;
}
enable_irq_wake(chip->gpio_int_n_irq);
i2c_set_clientdata(client, chip);
return ret;
tcpm_unregister_port:
tcpm_unregister_port(chip->tcpm_port);
fwnode_handle_put(chip->tcpc_dev.fwnode);
destroy_workqueue:
fusb302_debugfs_exit(chip);
destroy_workqueue(chip->wq);
return ret;
}
2.6.2 linux 4.19
配置
如果你使用的是linux 4.19
内核,则配置Fairchild fusb302 Support
驱动,将drivers/mfd/fusb302.c
编译到内核;
Device Driver --->
<*> Fairchild fusb302 Support
linux 6.3
为啥不配置这个呢?因此linux 6.3
内核驱动没有带有这个驱动,除非我们自己移植过来。
需要注意的是drivers/mfd/fusb302.c
驱动并会注册extcon
设备;因此能够识别是接入了USB
主机或USB
设备。
drivers/mfd/fusb302.c
的probe
函数:
static int fusb30x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct fusb30x_chip *chip;
struct PD_CAP_INFO *pd_cap_info;
int ret;
char *string[2];
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
if (fusb30x_port_used == 0xff)
return -1;
chip->port_num = fusb30x_port_used++;
fusb30x_port_info[chip->port_num] = chip;
chip->dev = &client->dev;
chip->regmap = devm_regmap_init_i2c(client, &fusb302_regmap_config);
if (IS_ERR(chip->regmap)) {
dev_err(&client->dev, "Failed to allocate regmap!\n");
return PTR_ERR(chip->regmap);
}
ret = fusb_initialize_gpio(chip);
if (ret)
return ret;
fusb_initialize_timer(chip);
chip->fusb30x_wq = create_workqueue("fusb302_wq");
INIT_WORK(&chip->work, fusb302_work_func);
chip->role = ROLE_MODE_NONE;
chip->try_role = ROLE_MODE_NONE;
if (!of_property_read_string(chip->dev->of_node, "fusb302,role",
(const char **)&string[0])) {
if (!strcmp(string[0], "ROLE_MODE_DRP"))
chip->role = ROLE_MODE_DRP;
else if (!strcmp(string[0], "ROLE_MODE_DFP"))
chip->role = ROLE_MODE_DFP;
else if (!strcmp(string[0], "ROLE_MODE_UFP"))
chip->role = ROLE_MODE_UFP;
}
if (chip->role == ROLE_MODE_NONE) {
dev_warn(chip->dev,
"Can't get property of role, set role to default DRP\n");
chip->role = ROLE_MODE_DRP;
string[0] = "ROLE_MODE_DRP";
}
if (!of_property_read_string(chip->dev->of_node, "fusb302,try_role",
(const char **)&string[1])) {
if (!strcmp(string[1], "ROLE_MODE_DFP"))
chip->try_role = ROLE_MODE_DFP;
else if (!strcmp(string[1], "ROLE_MODE_UFP"))
chip->try_role = ROLE_MODE_UFP;
}
if (chip->try_role == ROLE_MODE_NONE)
string[1] = "ROLE_MODE_NONE";
chip->vconn_supported = true;
tcpm_init(chip);
tcpm_set_rx_enable(chip, 0);
chip->conn_state = unattached;
tcpm_set_cc(chip, chip->role);
chip->n_caps_used = 1;
chip->source_power_supply[0] = 0x64;
chip->source_max_current[0] = 0x96;
pd_cap_info = &chip->pd_cap_info;
pd_cap_info->dual_role_power = 1;
pd_cap_info->data_role_swap = 1;
pd_cap_info->externally_powered = 1;
pd_cap_info->usb_suspend_support = 0;
pd_cap_info->usb_communications_cap = 0;
pd_cap_info->supply_type = 0;
pd_cap_info->peak_current = 0;
chip->extcon = devm_extcon_dev_allocate(&client->dev, fusb302_cable);
if (IS_ERR(chip->extcon)) {
dev_err(&client->dev, "allocat extcon failed\n");
return PTR_ERR(chip->extcon);
}
ret = devm_extcon_dev_register(&client->dev, chip->extcon);
if (ret) {
dev_err(&client->dev, "failed to register extcon: %d\n",
ret);
return ret;
}
ret = extcon_set_property_capability(chip->extcon, EXTCON_USB,
EXTCON_PROP_USB_TYPEC_POLARITY);
if (ret) {
dev_err(&client->dev,
"failed to set USB property capability: %d\n",
ret);
return ret;
}
ret = extcon_set_property_capability(chip->extcon, EXTCON_USB_HOST,
EXTCON_PROP_USB_TYPEC_POLARITY);
if (ret) {
dev_err(&client->dev,
"failed to set USB_HOST property capability: %d\n",
ret);
return ret;
}
ret = extcon_set_property_capability(chip->extcon, EXTCON_DISP_DP,
EXTCON_PROP_USB_TYPEC_POLARITY);
if (ret) {
dev_err(&client->dev,
"failed to set DISP_DP property capability: %d\n",
ret);
return ret;
}
ret = extcon_set_property_capability(chip->extcon, EXTCON_USB,
EXTCON_PROP_USB_SS);
if (ret) {
dev_err(&client->dev,
"failed to set USB USB_SS property capability: %d\n",
ret);
return ret;
}
ret = extcon_set_property_capability(chip->extcon, EXTCON_USB_HOST,
EXTCON_PROP_USB_SS);
if (ret) {
dev_err(&client->dev,
"failed to set USB_HOST USB_SS property capability: %d\n",
ret);
return ret;
}
ret = extcon_set_property_capability(chip->extcon, EXTCON_DISP_DP,
EXTCON_PROP_USB_SS);
if (ret) {
dev_err(&client->dev,
"failed to set DISP_DP USB_SS property capability: %d\n",
ret);
return ret;
}
ret = extcon_set_property_capability(chip->extcon, EXTCON_CHG_USB_FAST,
EXTCON_PROP_USB_TYPEC_POLARITY);
if (ret) {
dev_err(&client->dev,
"failed to set USB_PD property capability: %d\n", ret);
return ret;
}
i2c_set_clientdata(client, chip);
spin_lock_init(&chip->irq_lock);
chip->enable_irq = 1;
chip->gpio_int_irq = gpiod_to_irq(chip->gpio_int);
if (chip->gpio_int_irq < 0) {
dev_err(&client->dev,
"Unable to request IRQ for INT_N GPIO! %d\n",
ret);
ret = chip->gpio_int_irq;
goto IRQ_ERR;
}
ret = devm_request_threaded_irq(&client->dev,
chip->gpio_int_irq,
NULL,
cc_interrupt_handler,
IRQF_ONESHOT | IRQF_TRIGGER_LOW,
client->name,
chip);
if (ret) {
dev_err(&client->dev, "irq request failed\n");
goto IRQ_ERR;
}
dev_info(chip->dev,
"port %d probe success with role %s, try_role %s\n",
chip->port_num, string[0], string[1]);
chip->input = devm_input_allocate_device(&client->dev);
if (!chip->input) {
dev_err(chip->dev, "Can't allocate input dev\n");
ret = -ENOMEM;
goto IRQ_ERR;
}
chip->input->name = "Typec_Headphone";
chip->input->phys = "fusb302/typec";
input_set_capability(chip->input, EV_SW, SW_HEADPHONE_INSERT);
ret = input_register_device(chip->input);
if (ret) {
dev_err(chip->dev, "Can't register input device: %d\n", ret);
goto IRQ_ERR;
}
return 0;
IRQ_ERR:
destroy_workqueue(chip->fusb30x_wq);
return ret;
}
2.7 保存配置
配置完内核之后记得保存配置:
存档:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# mv rk3399_defconfig ./arch/arm64/configs/
重新配置内核(如果不想重新编译内核,可以存档一份到.config
):
root@zhengyang:/work/sambashare/rk3399/linux-6.3# make rk3399_defconfig
2.8 烧录内核
2.8.1 编译内核
在linux
内核根目录下执行如下命令进行编译内核:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# make -j8
u-boot-2023.04
路径下的mkimage
工具拷贝过来,然后在命令行使用mkimage
工具编译即可:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# cp ../u-boot-2023.04/tools/mkimage ./
root@zhengyang:/work/sambashare/rk3399/linux-6.3# ./mkimage -f kernel.its kernel.itb
2.8.2 通过tftp
烧录内核
给开发板上电,同时连接上网线,进入uboot
命令行。我们将内核拷贝到tftp
文件目录:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# cp kernel.itb /work/tftpboot/
接着给开发板上电。通过uboot
命令行将kernel.itb
下到内存地址0x10000000
处:
=> tftp 0x10000000 kernel.itb
通过mmc write
命令将内核镜像烧录到eMMC
第0x8000
个扇区处:
=> mmc erase 0x8000 0xA000
=> mmc write 0x10000000 0x8000 0xA000
2.8.3 启动内核
我们重新启动开发板,我们会看到与USB
相关的日志:
[ 1.829924] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
[ 1.830411] ehci-platform fe380000.usb: EHCI Host Controller
[ 1.830442] ohci-platform fe3a0000.usb: Generic Platform OHCI controller
[ 1.830485] ohci-platform fe3a0000.usb: new USB bus registered, assigned bus number 1
[ 1.830590] ehci-platform fe3c0000.usb: EHCI Host Controller
[ 1.830609] ohci-platform fe3e0000.usb: Generic Platform OHCI controller
[ 1.830621] ehci-platform fe3c0000.usb: new USB bus registered, assigned bus number 2
[ 1.830638] ohci-platform fe3e0000.usb: new USB bus registered, assigned bus number 3
[ 1.830658] ohci-platform fe3a0000.usb: irq 53, io mem 0xfe3a0000
[ 1.830761] ehci-platform fe3c0000.usb: irq 52, io mem 0xfe3c0000
[ 1.830789] ohci-platform fe3e0000.usb: irq 54, io mem 0xfe3e0000
[ 1.836166] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 4
[ 1.842483] ehci-platform fe380000.usb: new USB bus registered, assigned bus number 5
[ 1.850092] xhci-hcd xhci-hcd.0.auto: hcc params 0x0220fe64 hci version 0x110 quirks 0x0000000002010010
[ 1.853065] ehci-platform fe3c0000.usb: USB 2.0 started, EHCI 1.00
[ 1.853516] usb usb2: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 6.03
[ 1.853532] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 1.853544] usb usb2: Product: EHCI Host Controller
[ 1.853553] usb usb2: Manufacturer: Linux 6.3.0 ehci_hcd
[ 1.853562] usb usb2: SerialNumber: fe3c0000.usb
[ 1.854382] hub 2-0:1.0: USB hub found
[ 1.854450] hub 2-0:1.0: 1 port detected
[ 1.858836] ehci-platform fe380000.usb: irq 51, io mem 0xfe380000
[ 1.865071] xhci-hcd xhci-hcd.0.auto: irq 49, io mem 0xfe800000
[ 1.885063] ehci-platform fe380000.usb: USB 2.0 started, EHCI 1.00
[ 1.890257] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
[ 1.897120] usb usb5: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 6.03
[ 2.023756] usb usb5: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 2.031870] usb usb5: Product: EHCI Host Controller
[ 2.037347] usb usb5: Manufacturer: Linux 6.3.0 ehci_hcd
[ 2.043306] usb usb5: SerialNumber: fe380000.usb
[ 2.049117] hub 5-0:1.0: USB hub found
[ 2.053375] hub 5-0:1.0: 1 port detected
[ 2.058339] usb usb1: New USB device found, idVendor=1d6b, idProduct=0001, bcdDevice= 6.03
[ 2.067630] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 2.075719] usb usb1: Product: Generic Platform OHCI controller
[ 2.082361] usb usb1: Manufacturer: Linux 6.3.0 ohci_hcd
[ 2.088316] usb usb1: SerialNumber: fe3a0000.usb
[ 2.094011] hub 1-0:1.0: USB hub found
[ 2.098273] hub 1-0:1.0: 1 port detected
[ 2.103093] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 6
[ 2.103266] usb usb3: New USB device found, idVendor=1d6b, idProduct=0001, bcdDevice= 6.03
[ 2.111691] xhci-hcd xhci-hcd.0.auto: Host supports USB 3.0 SuperSpeed
[ 2.120951] usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 2.136415] usb usb3: Product: Generic Platform OHCI controller
[ 2.143068] usb usb3: Manufacturer: Linux 6.3.0 ohci_hcd
[ 2.149052] usb usb3: SerialNumber: fe3e0000.usb
[ 2.154791] hub 3-0:1.0: USB hub found
[ 2.159046] hub 3-0:1.0: 1 port detected
[ 2.164005] usb usb4: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 6.03
[ 2.173296] usb usb4: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 2.181386] usb usb4: Product: xHCI Host Controller
[ 2.186857] usb usb4: Manufacturer: Linux 6.3.0 xhci-hcd
[ 2.192813] usb usb4: SerialNumber: xhci-hcd.0.auto
[ 2.198818] hub 4-0:1.0: USB hub found
[ 2.203079] hub 4-0:1.0: 1 port detected
[ 2.207872] usb usb6: We don't know the algorithms for LPM for this host, disabling LPM.
[ 2.217093] usb usb6: New USB device found, idVendor=1d6b, idProduct=0003, bcdDevice= 6.03
[ 2.226375] usb usb6: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 2.234485] usb usb6: Product: xHCI Host Controller
[ 2.239956] usb usb6: Manufacturer: Linux 6.3.0 xhci-hcd
[ 2.245911] usb usb6: SerialNumber: xhci-hcd.0.auto
[ 2.251953] hub 6-0:1.0: USB hub found
[ 2.256206] hub 6-0:1.0: 1 port detected
[ 2.261191] xhci-hcd xhci-hcd.1.auto: xHCI Host Controller
[ 2.267479] xhci-hcd xhci-hcd.1.auto: new USB bus registered, assigned bus number 7
[ 2.276205] xhci-hcd xhci-hcd.1.auto: hcc params 0x0220fe64 hci version 0x110 quirks 0x0000000002010010
[ 2.286876] xhci-hcd xhci-hcd.1.auto: irq 50, io mem 0xfe900000
[ 2.293711] xhci-hcd xhci-hcd.1.auto: xHCI Host Controller
[ 2.299883] xhci-hcd xhci-hcd.1.auto: new USB bus registered, assigned bus number 8
[ 2.308563] xhci-hcd xhci-hcd.1.auto: Host supports USB 3.0 SuperSpeed
[ 2.316043] usb usb7: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 6.03
[ 2.325407] usb usb7: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 2.333513] usb usb7: Product: xHCI Host Controller
[ 2.338977] usb usb7: Manufacturer: Linux 6.3.0 xhci-hcd
[ 2.345017] usb usb7: SerialNumber: xhci-hcd.1.auto
[ 2.351075] hub 7-0:1.0: USB hub found
[ 2.355332] hub 7-0:1.0: 1 port detected
[ 2.360123] usb usb8: We don't know the algorithms for LPM for this host, disabling LPM.
[ 2.369320] usb usb8: New USB device found, idVendor=1d6b, idProduct=0003, bcdDevice= 6.03
[ 2.378593] usb usb8: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 2.386698] usb usb8: Product: xHCI Host Controller
[ 2.392169] usb usb8: Manufacturer: Linux 6.3.0 xhci-hcd
[ 2.398123] usb usb8: SerialNumber: xhci-hcd.1.auto
[ 2.404138] hub 8-0:1.0: USB hub found
[ 2.408398] hub 8-0:1.0: 1 port detected
[ 2.414435] usbcore: registered new interface driver usb-storage
[ 2.421325] usbcore: registered new interface driver pl2303
[ 2.427613] usbserial: USB Serial support registered for pl2303
[ 3.598344] usbcore: registered new interface driver uvcvideo
[ 3.718570] usbcore: registered new interface driver usbhid
[ 3.730651] usbhid: USB HID core driver
[ 3.744550] usbcore: registered new interface driver snd-usb-audio
从上面日志上可以看到总共注册了8个USB
总线,编号依次从1~8。每个USB
总线上对应一个USB
控制器,一共有8个USB
控制器;
-
ohci-platform fe3a0000.usb
:USB
总线编号为1,对应设备节点usb_host0_ohci
,对应开发板上接口为USBH2
; -
ehci-platform fe3c0000.usb
:USB
总线编号为2,对应设备节点usb_host1_ehci
,对应开发板上接口为USBH3
; -
ohci-platform fe3e0000.usb
:USB
总线编号为3,对应设备节点usb_host1_ohci
,对应开发板上接口为USBH3
; -
xhci-hcd xhci-hcd.0.auto(fe800000.usb)
:USB
总线编号为4,对应设备节点usbdrd3_0
,对应开发板上接口为Type-C/DP
; -
ehci-platform fe380000.usb
:USB
总线编号为5,对应设备节点usb_host0_ehci
,对应开发板上接口为USBH2
; -
xhci-hcd xhci-hcd.0.auto(fe800000.usb)
:USB
总线编号为6,对应设备节点usbdrd3_0
,对应开发板上接口为Type-C/DP
; -
xhci-hcd xhci-hcd.1.auto(fe900000.usb)
:USB
总线编号为7,对应设备节点usbdrd3_1
,对应开发板上接口为CON5
; -
xhci-hcd xhci-hcd.1.auto(fe900000.usb)
:USB
总线编号为8,对应设备节点usbdrd3_1
,对应开发板上接口为CON5
;
三、测试USB
设备
我们接下来在开发板USB2.0 Host Type-A
、USB3.0 Host Type-A
接口插入不同的USB
设备进行测试。
3.1 测试USB
鼠标
我们将USB
鼠标接到开发板其中一个USB2.0 Host Type-A
接口(对应开发板上的USBH3
), 我们可以在内核日志中,找到USB
鼠标信息的日志:
[ 1457.916575] usb 3-1: new full-speed USB device number 2 using ohci-platform
[ 1458.149684] usb 3-1: New USB device found, idVendor=046d, idProduct=c52b, bcdDevice=24.11
[ 1458.149723] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 1458.149740] usb 3-1: Product: USB Receiver
[ 1458.149754] usb 3-1: Manufacturer: Logitech
[ 1458.161331] input: Logitech USB Receiver as /devices/platform/fe3e0000.usb/usb3/3-1/3-1:1.0/0003:046D:C52B.0001/input/input1
[ 1458.221766] hid-generic 0003:046D:C52B.0001: input: USB HID v1.11 Keyboard [Logitech USB Receiver] on usb-fe3e0000.usb-1/input0
[ 1458.230238] input: Logitech USB Receiver Mouse as /devices/platform/fe3e0000.usb/usb3/3-1/3-1:1.1/0003:046D:C52B.0002/input/input2
[ 1458.230914] input: Logitech USB Receiver Consumer Control as /devices/platform/fe3e0000.usb/usb3/3-1/3-1:1.1/0003:046D:C52B.0002/input/input3
[ 1458.289373] input: Logitech USB Receiver System Control as /devices/platform/fe3e0000.usb/usb3/3-1/3-1:1.1/0003:046D:C52B.0002/input/input4
[ 1458.290293] hid-generic 0003:046D:C52B.0002: input,hiddev96: USB HID v1.11 Mouse [Logitech USB Receiver] on usb-fe3e0000.usb-1/input1
[ 1458.297793] hid-generic 0003:046D:C52B.0003: hiddev97: USB HID v1.11 Device [Logitech USB Receiver] on usb-fe3e0000.usb-1/input2
此时可以在ubuntu
桌面系统测试鼠标,可以发现是可以正常使用的。
USB
鼠标工作在全速模式下,OHCI
控制器,USB1.1
通信协议,使用的USB
总线编号为3,设备编号为2。
系统检测到了Logitech
(罗技)的鼠标,如果成功驱动的话就会在/dev/input
目录下生成一个名为eventX(X=0,1,2,3…)
的文件,这个就是我们前面讲的输入子系统,鼠标和键盘都是作为输入子系统设备的。
3.2 测试USB
键盘
(1) 我们将USB
键盘接到开发板另一个USB2.0 Host Type-A
接口(对应开发板上的USBH2
),在内核日志中,找到USB
键盘信息的日志:
[ 1619.954338] usb 1-1: new low-speed USB device number 2 using ohci-platform
[ 1620.183564] usb 1-1: New USB device found, idVendor=1a2c, idProduct=4d7e, bcdDevice= 1.10
[ 1620.183603] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 1620.183620] usb 1-1: Product: USB Keyboard
[ 1620.183634] usb 1-1: Manufacturer: SEMICO
[ 1620.193197] input: SEMICO USB Keyboard as /devices/platform/fe3a0000.usb/usb1/1-1/1-1:1.0/0003:1A2C:4D7E.0004/input/input6
[ 1620.251611] hid-generic 0003:1A2C:4D7E.0004: input: USB HID v1.10 Keyboard [SEMICO USB Keyboard] on usb-fe3a0000.usb-1/input0
[ 1620.263525] input: SEMICO USB Keyboard Consumer Control as /devices/platform/fe3a0000.usb/usb1/1-1/1-1:1.1/0003:1A2C:4D7E.0005/input/input7
[ 1620.323415] input: SEMICO USB Keyboard System Control as /devices/platform/fe3a0000.usb/usb1/1-1/1-1:1.1/0003:1A2C:4D7E.0005/input/input8
[ 1620.324115] input: SEMICO USB Keyboard as /devices/platform/fe3a0000.usb/usb1/1-1/1-1:1.1/0003:1A2C:4D7E.0005/input/input10
[ 1620.324871] hid-generic 0003:1A2C:4D7E.0005: input,hiddev98: USB HID v1.10 Keyboard [SEMICO USB Keyboard] on usb-fe3a0000.usb-1/input1
此时可以在ubuntu
桌面系统测试键盘,可以发现是可以正常使用的。
USB
键盘工作在低速模式下,OHCI
控制器,USB1.0
通信协议,使用的USB
总线编号为1,设备编号为2。
(2) 拔掉USB
键盘,尝试将USB
键盘接到USB3.0 Host Type-A
接口(对应开发板上的CON5
),在内核日志中,找到USB
键盘信息的日志:
[ 1665.652164] usb 1-1: USB disconnect, device number 2
[ 1678.668389] usb 7-1: new low-speed USB device number 2 using xhci-hcd
[ 1678.822673] usb 7-1: New USB device found, idVendor=1a2c, idProduct=4d7e, bcdDevice= 1.10
[ 1678.822713] usb 7-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 1678.822729] usb 7-1: Product: USB Keyboard
[ 1678.822743] usb 7-1: Manufacturer: SEMICO
[ 1678.850429] input: SEMICO USB Keyboard as /devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7/7-1/7-1:1.0/0003:1A2C:4D7E.0006/input/input11
[ 1678.909715] hid-generic 0003:1A2C:4D7E.0006: input: USB HID v1.10 Keyboard [SEMICO USB Keyboard] on usb-xhci-hcd.1.auto-1/input0
[ 1678.921243] input: SEMICO USB Keyboard Consumer Control as /devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7/7-1/7-1:1.1/0003:1A2C:4D7E.0007/input/input12
[ 1678.981216] input: SEMICO USB Keyboard System Control as /devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7/7-1/7-1:1.1/0003:1A2C:4D7E.0007/input/input13
[ 1678.981907] input: SEMICO USB Keyboard as /devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7/7-1/7-1:1.1/0003:1A2C:4D7E.0007/input/input15
[ 1678.982716] hid-generic 0003:1A2C:4D7E.0007: input,hiddev98: USB HID v1.10 Keyboard [SEMICO USB Keyboard] on usb-xhci-hcd.1.auto-1/input1
此时可以在ubuntu
桌面系统测试键盘,可以发现是可以正常使用的。
USB
键盘工作在低速模式下,xHCI
控制器,USB1.0
通信协议,使用的USB
总线编号为7,设备编号为2。
3.3 测试USB
摄像头
我们将USB
摄像头接到开发板的USB3.0 Host Type-A
接口(对应开发板上的CON5
),在内核日志中,找到USB
摄像头信息的日志:
[ 2305.074204] usb 7-1: USB disconnect, device number 2
[ 2323.296616] usb 7-1: new high-speed USB device number 3 using xhci-hcd
[ 2323.483982] usb 7-1: New USB device found, idVendor=0c45, idProduct=6340, bcdDevice= 0.00
[ 2323.484022] usb 7-1: New USB device strings: Mfr=2, Product=1, SerialNumber=0
[ 2323.484038] usb 7-1: Product: USB 2.0 Camera
[ 2323.484052] usb 7-1: Manufacturer: Sonix Technology Co., Ltd.
[ 2323.495745] usb 7-1: Found UVC 1.00 device USB 2.0 Camera (0c45:6340)
[ 2323.519918] input: USB 2.0 Camera: USB Camera as /devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7/7-1/7-1:1.0/input/input16
USB
键盘工作在高速模式下,xHCI
控制器,USB2.0
通信协议,使用的USB
总线编号为7,设备编号为2。
从上面的信息可以看到这里,已经识别到了我们的USB
摄像头,VID=0c45
、PID=6340
。
安装应用程序茄子:
root@rk3399:/# sudo apt-get install cheese
在ubuntu
输入cheese
命令捕捉视频:
root@rk3399:/# cheese
如图所示:
3.4 测试移动硬盘
准备好一个移动硬盘,注意移动硬盘要为NFTS
格式的!NTFS
和exFAT
由于版权问题所以在Linux
下支持的不完善,操作的话可能会有问题,比如只能读,不能写或者无法识别等。
准备好以后将移动硬盘插入到开发板USB3.0 Host Type-A
接口(对应开发板上的CON5
),在内核日志中,找到移动硬盘信息的日志:
[ 3341.772611] usb 7-1: USB disconnect, device number 3
[ 3393.909693] usb 8-1: new SuperSpeed USB device number 2 using xhci-hcd
[ 3393.932045] usb 8-1: New USB device found, idVendor=0480, idProduct=b200, bcdDevice= 1.00
[ 3393.932085] usb 8-1: New USB device strings: Mfr=2, Product=3, SerialNumber=1
[ 3393.932102] usb 8-1: Product: External USB 3.0
[ 3393.932115] usb 8-1: Manufacturer: TOSHIBA
[ 3393.932129] usb 8-1: SerialNumber: 2018010302552D
[ 3393.936501] usb-storage 8-1:1.0: USB Mass Storage device detected
[ 3393.937468] scsi host0: usb-storage 8-1:1.0
[ 3394.970703] scsi 0:0:0:0: Direct-Access TOSHIBA External USB 3.0 0 PQ: 0 ANSI: 6
[ 3394.972008] sd 0:0:0:0: Attached scsi generic sg0 type 0
[ 3394.973469] sd 0:0:0:0: [sda] Spinning up disk...
[ 3395.993613] ...ready
[ 3398.068783] sd 0:0:0:0: [sda] 1953525168 512-byte logical blocks: (1.00 TB/932 GiB)
[ 3398.069873] sd 0:0:0:0: [sda] Write Protect is off
[ 3398.069891] sd 0:0:0:0: [sda] Mode Sense: 43 00 00 00
[ 3398.071119] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 3398.114863] sda: sda1 sda2 sda3 sda4 < sda5 >
[ 3398.116779] sd 0:0:0:0: [sda] Attached SCSI disk
移动硬盘工作在超高速模式下,xHCI
控制器,USB3.0
通信协议,使用的USB
总线编号为8,设备编号为2。
可以看出,系统检测到移动硬盘插入,大小为1TB
,对应的设备文件为/dev/sda
和/dev/sda1~5
,大家可以查看一下/dev
目录下有没有sda
和sda1~5
这6个文件;
root@rk3399:/# ll /dev/sda*
brw-rw---- 1 root disk 8, 0 Sep 16 15:28 /dev/sda
brw-rw---- 1 root disk 8, 1 Sep 16 15:28 /dev/sda1
brw-rw---- 1 root disk 8, 2 Sep 16 15:28 /dev/sda2
brw-rw---- 1 root disk 8, 3 Sep 16 15:28 /dev/sda3
brw-rw---- 1 root disk 8, 4 Sep 16 15:28 /dev/sda4
brw-rw---- 1 root disk 8, 5 Sep 16 15:28 /dev/sda5
其中:
/dev/sda
:是整个移动硬盘;/dev/sda1~5
: 是移动硬盘的第1个到第5个分区,这是是由于我在PC
上已经将移动硬盘分了5个分区;
(1) 要想访问移动硬盘我们需要先对移动硬盘进行挂载,理论上挂载到任意一个目录下都可以.
测试发现ubuntu系统会自动将移动硬盘下的各个分区挂载到/media/root
下;
root@rk3399:/media/root# df -T
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/root ext4 14801956 4998424 9143588 36% /
devtmpfs devtmpfs 1950140 0 1950140 0% /dev
tmpfs tmpfs 1972572 0 1972572 0% /dev/shm
tmpfs tmpfs 394516 1760 392756 1% /run
tmpfs tmpfs 5120 4 5116 1% /run/lock
tmpfs tmpfs 1972572 0 1972572 0% /sys/fs/cgroup
tmpfs tmpfs 394512 16 394496 1% /run/user/0
/dev/sda3 fuseblk 209715196 14878708 194836488 8% /media/root/小白PE工具盘1
/dev/sda5 fuseblk 347613180 14758876 332854304 5% /media/root/小白PE工具盘
/dev/sda2 fuseblk 209715196 42328260 167386936 21% /media/root/程序
/dev/sda1 fuseblk 209715196 13973916 195741280 7% /media/root/学业
(2) 这里我创建一个/mnt/usb_disk
目录,然后将移动硬盘第一个分区挂载到/mnt/usb_disk
目录下,命令如下:
root@rk3399:/# mkdir -p /mnt/usb_disk
root@rk3399:/# mount /dev/sda1 /mnt/usb_disk/ -t ntfs -o iocharset=utf8
其中:
-t ntfs
:指定挂载所使用的文件系统类型,这里设置为ntfs
,也就是NTFS
文件系统;-o iocharset=utf8
:设置硬盘编码格式为utf8
,否则的话移动硬盘里面的中文会显示乱码;
如果挂载的时候出现如下错误:
root@rk3399:/# mount /dev/sda1 /mnt/usb_disk/ -t ntfs -o iocharset=utf8
Mount is denied because the NTFS volume is already exclusively opened.
The volume may be already mounted, or another software may use it which
could be identified for example by the help of the 'fuser' command.
通过错误语句的输出可以知道NTFS
卷被拒绝是因为已经执行打开,可能已经被挂载或者有应用程序正在使用它,可以使用fuser
命令显示正在使用指定的file
,file system
或者socket
的进程信息。
如fuser -m -u /dev/sda1
使用-m -u
显示正在使用/dev/sda1
的进程PID
以及用户名称,如我输入上述命令后显示的情况:
root@rk3399:/# fuser -m -u /dev/sda1
/dev/sda1: 5168(root)
root@rk3399:/# kill 5168
表明是PID
为5168的进程正在使用它,可以使用kill
命令杀死该进程,此时在使用mount
命令就不会出错了。
挂载成功以后进入到/mnt/usb_disk
目录下,输入ls
命令查看移动硬盘文件;
root@rk3399:/# cd /mnt/usb_disk/
root@rk3399:/mnt/usb_disk# ll
total 60
drwxrwxrwx 1 root root 8192 Jun 22 2021 '$RECYCLE.BIN'/
drwxrwxrwx 1 root root 12288 Jun 22 2021 ./
drwxr-xr-x 3 root root 4096 Sep 16 15:37 ../
drwxrwxrwx 1 root root 4096 Jun 22 2021 1.led/
drwxrwxrwx 1 root root 4096 Jun 22 2021 3.myboot/
drwxrwxrwx 1 root root 4096 Jun 22 2021 4.mmu/
drwxrwxrwx 1 root root 4096 Jun 22 2021 5.nadflash/
drwxrwxrwx 1 root root 8192 Jun 22 2021 6.interupt/
drwxrwxrwx 1 root root 4096 Jun 22 2021 7.uart/
drwxrwxrwx 1 root root 4096 Jun 22 2021 8.do_bootm_linux/
drwxrwxrwx 1 root root 4096 Dec 22 2021 'System Volume Information'/
至此移动硬盘就能正常读写操作了,直接对/mnt/usb_disk
目录进行操作就行了。如果要拔出移动硬盘要执行一个sync
命令进行同步,然后在使用unmount
进行移动硬盘卸载,命令如下所示:
root@rk3399:/mnt/usb_disk# sync
root@rk3399:/mnt/usb_disk# cd /
root@rk3399:/# umount /mnt/usb_disk
3.5 测试Type-C
触摸屏
现在我手里有一个NanoPC-T4
开发板,同时还有一个15.6
英寸HDMI
接口显示屏,并且该显示屏支持Type-C
十点触摸。
(1) 配置USB3.0/2.0 OTG0
的工作模式为Host
(主机),这种做法只会临时有效:
root@rk3399:/lib/modules/6.3.0# cat /sys/kernel/debug/usb/fe800000.usb/mode
otg
root@rk3399:/lib/modules/6.3.0# echo host > /sys/kernel/debug/usb/fe800000.usb/mode
root@rk3399:/lib/modules/6.3.0# cat /sys/kernel/debug/usb/fe800000.usb/mode
host
如果想永久有效,可以通过修改设备树dr-mode = host
将工作配置为Host
(主机);具体可以参考:《Rockchip RK3399 - USB
触摸屏接口驱动》。
(2) 这里我们通过Type-C
线(两端都是Type-C
接口)将开发板USB3.0 Type-C
接口(对应开发板上的Type-C/DP
)与触摸屏的Type-C
接口连接起来。内核输出日志信息:
[ 2358.710215] usb 4-1: new full-speed USB device number 2 using xhci-hcd
[ 2358.862485] usb 4-1: New USB device found, idVendor=222a, idProduct=0001, bcdDevice= 1.00
[ 2358.862525] usb 4-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2358.862542] usb 4-1: Product: SingWon-CTP-V1.18A
[ 2358.862555] usb 4-1: Manufacturer: UsbHID
[ 2358.862569] usb 4-1: SerialNumber: 6F6A099B1133
[ 2358.899245] input: UsbHID SingWon-CTP-V1.18A as /devices/platform/usb@fe800000/fe800000.usb/xhci-hcd.0.auto/usb4/4-1/4-1:1.0/0003:222A:0001.0003/input/input6
[ 2358.899571] hid-generic 0003:222A:0001.0003: input: USB HID v1.11 Device [UsbHID SingWon-CTP-V1.18A] on usb-xhci-hcd.0.auto-1/input0
[ 2358.903930] input: UsbHID SingWon-CTP-V1.18A as /devices/platform/usb@fe800000/fe800000.usb/xhci-hcd.0.auto/usb4/4-1/4-1:1.1/0003:222A:0001.0004/input/input7
[ 2358.966870] hid-generic 0003:222A:0001.0004: input: USB HID v1.12 Keyboard [UsbHID SingWon-CTP-V1.18A] on usb-xhci-hcd.0.auto-1/input1
此时可以在ubuntu
桌面系统测试触摸屏,可以发现触摸屏可以正常实用。
USB
触摸屏工作在全速模式下,xHCI
控制器,USB1.1
通信协议,使用的USB
总线编号为4,设备编号为2。
3.6 测试USB
4口HUB
集线器
这里我们将USB
4口HUB
集线器里连接到开发板USB3.0 Host Type-A
接口(对应开发板上的CON5
)。内核输出日志信息:
[ 232.825153] usb 7-1: new high-speed USB device number 4 using xhci-hcd
[ 232.975149] usb 7-1: New USB device found, idVendor=14cd, idProduct=8601, bcdDevice= 0.00
[ 232.975188] usb 7-1: New USB device strings: Mfr=1, Product=3, SerialNumber=0
[ 232.975204] usb 7-1: Product: USB 2.0 Hub
[ 232.975218] usb 7-1: Manufacturer: USB Device
[ 233.011052] hub 7-1:1.0: USB hub found
[ 233.011213] hub 7-1:1.0: 4 ports detected
USB
键盘工作在高速模式下,xHCI
控制器,USB2.0
通信协议,使用的USB
总线编号为7,设备编号为4。
从上面的信息可以看到这里,已经识别到了我们的USB
4口HUB
集线器,VID=14cd
、PID=8601
,并且有4个端口。
我们尝试在将USB
鼠标插入HUB
其中一个端口,内核输出日志信息:
[ 450.823397] usb 7-1.1: new full-speed USB device number 5 using xhci-hcd
[ 450.928638] usb 7-1.1: New USB device found, idVendor=046d, idProduct=c52b, bcdDevice=24.11
[ 450.928677] usb 7-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 450.928694] usb 7-1.1: Product: USB Receiver
[ 450.928707] usb 7-1.1: Manufacturer: Logitech
[ 451.031478] input: Logitech USB Receiver as /devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7/7-1/7-1.1/7-1.1:1.0/0003:046D:C52B.0006/input/input11
[ 451.092719] hid-generic 0003:046D:C52B.0006: input: USB HID v1.11 Keyboard [Logitech USB Receiver] on usb-xhci-hcd.1.auto-1.1/input0
[ 451.099030] input: Logitech USB Receiver Mouse as /devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7/7-1/7-1.1/7-1.1:1.1/0003:046D:C52B.0007/input/input12
[ 451.099733] input: Logitech USB Receiver Consumer Control as /devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7/7-1/7-1.1/7-1.1:1.1/0003:046D:C52B.0007/input/input13
[ 451.160075] input: Logitech USB Receiver System Control as /devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7/7-1/7-1.1/7-1.1:1.1/0003:046D:C52B.0007/input/input14
[ 451.160547] hid-generic 0003:046D:C52B.0007: input,hiddev97: USB HID v1.11 Mouse [Logitech USB Receiver] on usb-xhci-hcd.1.auto-1.1/input1
[ 451.165557] hid-generic 0003:046D:C52B.0008: hiddev98: USB HID v1.11 Device [Logitech USB Receiver] on usb-xhci-hcd.1.auto-1.1/input2
此时可以在ubuntu
桌面系统测试鼠标,可以发现是可以正常使用的。
USB
鼠标工作在全速模式下,xHCI
控制器,USB1.1
通信协议,使用的USB
总线编号为7,设备编号为5。
四、 模拟USB
设备
4.1 模拟存储设备
我们需要按照前面的内核配置将USB Gadget precomposed configurations
---> Mass Storage Gadget
驱动编译成模块。使用的时候直接输入命令加载驱动即可。
(1) 配置好以后重新linux
内核,会得到三个.ko
驱动文件:
drivers/usb/gadget/libcomposite.ko
drivers/usb/gadget/function/usb_f_mass_storage.ko
drivers/usb/gadget/legacy/g_mass_storage.ko
(2) 重新烧录内核,启动开发板。将上述三个.ko
模块拷贝到开发板/lib/modules/6.3.0
(如果没有该目录,自行创建),命令如下:
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/modules.builtin /lib/modules/6.3.0
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/modules.order /lib/modules/6.3.0
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/drivers/usb/gadget/libcomposite.ko /lib/modules/6.3.0
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/drivers/usb/gadget/function/usb_f_mass_storage.ko /lib/modules/6.3.0
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/drivers/usb/gadget/legacy/g_mass_storage.ko /lib/modules/6.3.0
(3) 在开发板插入一个移动硬盘到我们的USB3.0 Host Type-A
接口,并使用Type-C
连接线,并按照之前介绍的将/dev/sda1分区挂载到/mnt/usb_disk
目录下;
root@rk3399:/# mount /dev/sda1 /mnt/usb_disk/ -t ntfs -o iocharset=utf8
最后将开发板USB3.0 Type-C
接口与PC
连接起来。
(4) 配置USB3.0/2.0 OTG0
的工作模式为Device
(设备),这种做法只会临时有效:
root@rk3399:/lib/modules/6.3.0# cat /sys/kernel/debug/usb/fe800000.usb/mode
otg
root@rk3399:/lib/modules/6.3.0# echo device > /sys/kernel/debug/usb/fe800000.usb/mode
root@rk3399:/lib/modules/6.3.0# cat /sys/kernel/debug/usb/fe800000.usb/mode
device
如果想永久有效,可以通过修改设备树dr-mode = peripheral
将工作配置为Device
(设备);
(5) 需要在加载模块之前建立该模块的依赖关系,也即必须用depmod
来更新一下/lib/modules/linux-6.3/modules.dep
文件;
root@rk3399:/lib/modules/6.3.0# cd /lib/modules/6.3.0
root@rk3399:/lib/modules/6.3.0# depmod -a
root@rk3399:/lib/modules/6.3.0# modprobe libcomposite
root@rk3399:/lib/modules/6.3.0# modprobe usb_f_mass_storage
root@rk3399:/lib/modules/6.3.0# modprobe g_mass_storage file=/dev/sda1 removable=1
modprobe
和insmode
的区别在于modprobe
可以动态加载依赖的驱动,而insmode
必须一个一个加载。加载g_mass_storage
的时候使用file
参数指定使用的大容量存储设备对应的/dev/sda1
。同时内核会输出如下日志:
[ 390.786425] Mass Storage Function, version: 2009/09/11
[ 390.786459] LUN: removable file: (no medium)
[ 390.786724] LUN: removable file: /dev/sda1
[ 390.786743] Number of LUNs=1
[ 390.786975] g_mass_storage gadget.0: Mass Storage Gadget, version: 2009/09/11
[ 390.786995] g_mass_storage gadget.0: userspace failed to provide iSerialNumber
[ 390.787005] g_mass_storage gadget.0: g_mass_storage ready
通过命令可以查看我们已经加载的驱动:
root@rk3399:/lib/modules/6.3.0# lsmod
Module Size Used by
#### 下面是我们刚才加载的 ######
g_mass_storage 16384 0
usb_f_mass_storage 69632 2 g_mass_storage
libcomposite 81920 2 usb_f_mass_storage,g_mass_storage
#### 下面是wifi相关的,忽略即可 #####
brcmfmac_wcc 16384 0
brcmfmac 348160 1 brcmfmac_wcc
cfg80211 901120 1 brcmfmac
brcmutil 24576 1 brcmfmac
如果加载成功的话PC
就会出现一个移动硬盘,如下图所示:
(6) 我们可以直接在电脑上对这个移动硬盘进行读写操作,实际上操作的就是我们的移动硬盘,操作完成以后要退出的话执行如下命令:
root@rk3399:/lib/modules/6.3.0# rmmod g_mass_storage
4.2 模拟声卡
我们需要按照前面的内核配置将USB Gadget precomposed configurations
---> Audio Gadget
驱动编译成模块。使用的时候直接输入命令加载驱动即可。
(1) 配置好以后重新linux
内核,会得到5个.ko
驱动文件:
drivers/usb/gadget/libcomposite.ko
drivers/usb/gadget/function/usb_f_uac1.ko
drivers/usb/gadget/function/u_audio.ko
drivers/usb/gadget/legacy/g_audio.ko
(2) 重新烧录内核,启动开发板。将上述5个.ko
模块拷贝到开发板/lib/modules/6.3.0
(如果没有该目录,自行创建),命令如下:
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/modules.builtin /lib/modules/6.3.0
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/modules.order /lib/modules/6.3.0
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/drivers/usb/gadget/libcomposite.ko /lib/modules/6.3.0
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/drivers/usb/gadget/function/usb_f_uac1.ko /lib/modules/6.3.0
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/drivers/usb/gadget/function/u_audio.ko /lib/modules/6.3.0
root@rk3399:/lib# scp -r [email protected]:/work/sambashare/rk3399/linux-6.3/drivers/usb/gadget/legacy/g_audio.ko /lib/modules/6.3.0
(3) 首先按照我们之前声卡驱动移植章节介绍的,保证声卡可以正常播放。
使用Type-C
连接线,将开发板USB3.0 Type-C
接口与PC
连接起来。
(4) 配置USB3.0/2.0 OTG0
的工作模式为Device
(设备),这种做法只会临时有效:
root@rk3399:/lib/modules/6.3.0# cat /sys/kernel/debug/usb/fe800000.usb/mode
otg
root@rk3399:/lib/modules/6.3.0# echo device > /sys/kernel/debug/usb/fe800000.usb/mode
root@rk3399:/lib/modules/6.3.0# cat /sys/kernel/debug/usb/fe800000.usb/mode
device
如果想永久有效,可以通过修改设备树dr-mode = peripheral
将工作配置为Device
(设备);
(5) 需要在加载模块之前建立该模块的依赖关系,也即必须用depmod
来更新一下/lib/modules/linux-6.3/modules.dep
文件;
root@rk3399:~# cd /lib/modules/6.3.0
root@rk3399:/lib/modules/6.3.0# depmod -a
root@rk3399:/lib/modules/6.3.0# modprobe libcomposite
root@rk3399:/lib/modules/6.3.0# modprobe u_audio
root@rk3399:/lib/modules/6.3.0# modprobe usb_f_uac1
root@rk3399:/lib/modules/6.3.0# modprobe g_audio
modprobe
和insmode
的区别在于modprobe
可以动态加载依赖的驱动,而insmode
必须一个一个加载。内核会输出如下日志:
[ 1863.468513] g_audio gadget.0: Linux USB Audio Gadget, version: Feb 2, 2012
[ 1863.468535] g_audio gadget.0: g_audio ready
通过命令可以查看我们已经加载的驱动:
root@rk3399:/lib/modules/6.3.0# lsmod
Module Size Used by
#### 下面是我们刚才加载的 ######
g_audio 16384 0
usb_f_uac1 36864 0
u_audio 32768 2 usb_f_uac1,usb_f_uac2
libcomposite 81920 5 usb_f_uac1,u_audio,g_audio,usb_f_mass_storage,usb_f_uac2
#### 下面是wifi相关的,忽略即可 #####
brcmfmac_wcc 16384 0
brcmfmac 348160 1 brcmfmac_wcc
cfg80211 901120 1 brcmfmac
brcmutil 24576 1 brcmfmac
加载完成以后稍等一会虚拟出一个USB
声卡,打开电脑的设备管理器,选择声音、视频和游戏控制器,会出现有一个名为Source/Sink
设备,如下图所示:
选择该设备,并通过PC
播放音乐,不过这里我测试始终没有声音输出,具体原因还不太清除;
(6) 移除驱动:
root@rk3399:/lib/modules/6.3.0# rmmod g_audio
五、调试接口
5.1 USB Gadget Configfs
之前我们介绍了如何模拟一个存储设备、声卡设备;此外还可以通过USB Gadget Configfs
来实现同样的功能。
5.1.1 挂载configfs
首先需要挂载configfs
到/config
目录下:
root@rk3399:/# mkdir /config
root@rk3399:/# mount -t configfs none /config
挂载完成后,会在/config
目录下生成usb_gadget
目录。
创建g1
文件夹,创建完g1
之后,会在该目录下生成很多配置目录;
root@rk3399:/# cd /config/usb_gadget/
root@rk3399:/config/usb_gadget# mkdir -p g1
root@rk3399:/config/usb_gadget# ll g1/
-rw-r--r-- 1 root root 4096 Sep 17 22:16 UDC
-rw-r--r-- 1 root root 4096 Sep 17 22:16 bDeviceClass
-rw-r--r-- 1 root root 4096 Sep 17 22:16 bDeviceProtocol
-rw-r--r-- 1 root root 4096 Sep 17 22:16 bDeviceSubClass
-rw-r--r-- 1 root root 4096 Sep 17 22:16 bMaxPacketSize0
-rw-r--r-- 1 root root 4096 Sep 17 22:16 bcdDevice
-rw-r--r-- 1 root root 4096 Sep 17 22:16 bcdUSB
drwxr-xr-x 2 root root 0 Sep 17 22:16 configs/
drwxr-xr-x 2 root root 0 Sep 17 22:16 functions/
-rw-r--r-- 1 root root 4096 Sep 17 22:16 idProduct
-rw-r--r-- 1 root root 4096 Sep 17 22:16 idVendor
-rw-r--r-- 1 root root 4096 Sep 17 22:16 max_speed
drwxr-xr-x 2 root root 0 Sep 17 22:16 os_desc/
drwxr-xr-x 2 root root 0 Sep 17 22:16 strings/
drwxr-xr-x 2 root root 0 Sep 17 22:16 webusb/
这里的g1
表示gadget 1
,一个UDC
对应一个gadget
,如果SoC
上有多个gadget
,可以创建多个gx
目录。
5.1.2 配置g1
(1) 配置PID
和VID
;
echo 0x1a2c > /config/usb_gadget/g1/idVendor
echo 0x4d7e > /config/usb_gadget/g1/idProduct
(2) 创建并配置string
字目录:
mkdir /config/usb_gadget/g1/strings/0x409
echo "0" > /config/usb_gadget/g1/strings/0x409/serialnumber
echo "SEMICO" > /config/usb_gadget/g1/strings/0x409/manufacturer
echo "USB Keyboard" > /config/usb_gadget/g1/strings/0x409/product
上面的配置信息大部分都是从USB
键盘设备信息中拷贝过来的。
(3) 创建configuration
和字符串:
mkdir /config/usb_gadget/g1/configs/c.1
mkdir /config/usb_gadget/g1/configs/c.1/strings/0x409
echo "mass_storage" > /config/usb_gadget/g1/configs/c.1/strings/0x409/configuration
这里的mass_storage
的名字不能随便起,需要根据modprobe
的function
驱动usb_f_mass_storage.ko
来决定,否则会出现错误。
(4) 创建functions
mkdir /config/usb_gadget/g1/functions/mass_storage.0
(5) 将functions
和configuration
关联起来:
ln -s /config/usb_gadget/g1/functions/mass_storage.0 /config/usb_gadget/g1/configs/c.1
上述配置之后,得到的结果为:
root@rk3399:/config# find .
.
./usb_gadget
./usb_gadget/g1
./usb_gadget/g1/webusb
./usb_gadget/g1/webusb/landingPage
./usb_gadget/g1/webusb/bVendorCode
./usb_gadget/g1/webusb/bcdVersion
./usb_gadget/g1/webusb/use
./usb_gadget/g1/os_desc
./usb_gadget/g1/os_desc/qw_sign
./usb_gadget/g1/os_desc/b_vendor_code
./usb_gadget/g1/os_desc/use
./usb_gadget/g1/strings
./usb_gadget/g1/strings/0x409
./usb_gadget/g1/strings/0x409/serialnumber
./usb_gadget/g1/strings/0x409/product
./usb_gadget/g1/strings/0x409/manufacturer
./usb_gadget/g1/configs
./usb_gadget/g1/configs/c.1
./usb_gadget/g1/configs/c.1/strings
./usb_gadget/g1/configs/c.1/strings/0x409
./usb_gadget/g1/configs/c.1/strings/0x409/configuration
./usb_gadget/g1/configs/c.1/bmAttributes
./usb_gadget/g1/configs/c.1/MaxPower
./usb_gadget/g1/functions
./usb_gadget/g1/functions/mass_storage.0
./usb_gadget/g1/functions/mass_storage.0/lun.0
./usb_gadget/g1/functions/mass_storage.0/lun.0/forced_eject
./usb_gadget/g1/functions/mass_storage.0/lun.0/inquiry_string
./usb_gadget/g1/functions/mass_storage.0/lun.0/nofua
./usb_gadget/g1/functions/mass_storage.0/lun.0/cdrom
./usb_gadget/g1/functions/mass_storage.0/lun.0/removable
./usb_gadget/g1/functions/mass_storage.0/lun.0/ro
./usb_gadget/g1/functions/mass_storage.0/lun.0/file
./usb_gadget/g1/functions/mass_storage.0/stall
./usb_gadget/g1/max_speed
./usb_gadget/g1/UDC
./usb_gadget/g1/bcdUSB
./usb_gadget/g1/bcdDevice
./usb_gadget/g1/idProduct
./usb_gadget/g1/idVendor
./usb_gadget/g1/bMaxPacketSize0
./usb_gadget/g1/bDeviceProtocol
./usb_gadget/g1/bDeviceSubClass
./usb_gadget/g1/bDeviceClass
(6) 配置USB3.0/2.0 OTG0
的工作模式为Device
(设备):
root@rk3399:/lib/modules/6.3.0# cat /sys/kernel/debug/usb/fe800000.usb/mode
otg
root@rk3399:/lib/modules/6.3.0# echo device > /sys/kernel/debug/usb/fe800000.usb/mode
root@rk3399:/lib/modules/6.3.0# cat /sys/kernel/debug/usb/fe800000.usb/mode
device
(7) 查看当前的UDC
,可见开发板上有1个UDC
,fe800000.usb
root@rk3399:/config# ll /sys/class/udc/
total 0
drwxr-xr-x 2 root root 0 Mar 15 2023 ./
drwxr-xr-x 78 root root 0 Mar 15 2023 ../
lrwxrwxrwx 1 root root 0 Sep 17 23:37 fe800000.usb -> '../../devices/platform/usb@fe800000/fe800000.usb/udc/fe800000.usb'/
配置当前gadget
对应的USB OTG
控制器, 执行如下命令;
echo fe800000.usb > /config/usb_gadget/g1/UDC
5.1.3 验证
使用Type-C
连接线,将开发板USB3.0 Type-C
接口与PC
连接起来。
上述的结果是只识别到一个mass storage
的设备,但是没有看到相应的磁盘信息。想要看到磁盘信息,可以更进一步的设置mass_storage
的backen file
属性。
5.1.4 补充
除了USB Gadget Configfs
之外,我又发现了一种模拟存储设备、声卡设备的方法,具体可以参考《zynq
下usb gadget
模拟网口、U
盘、串口》。
5.2 sysfs
5.2.1 USB
设备
所有USB
设备可以在/sys/bus/usb/devices
下找到;
root@rk3399:/# ll /sys/bus/usb/devices
total 0
drwxr-xr-x 2 root root 0 Mar 15 2023 ./
drwxr-xr-x 4 root root 0 Mar 15 2023 ../
lrwxrwxrwx 1 root root 0 Mar 15 2023 1-0:1.0 -> ../../../devices/platform/fe3a0000.usb/usb1/1-0:1.0/
lrwxrwxrwx 1 root root 0 Sep 16 21:50 1-1 -> ../../../devices/platform/fe3a0000.usb/usb1/1-1/
lrwxrwxrwx 1 root root 0 Sep 16 21:50 1-1:1.0 -> ../../../devices/platform/fe3a0000.usb/usb1/1-1/1-1:1.0/
lrwxrwxrwx 1 root root 0 Sep 16 21:50 1-1:1.1 -> ../../../devices/platform/fe3a0000.usb/usb1/1-1/1-1:1.1/
lrwxrwxrwx 1 root root 0 Mar 15 2023 2-0:1.0 -> ../../../devices/platform/fe3c0000.usb/usb2/2-0:1.0/
lrwxrwxrwx 1 root root 0 Mar 15 2023 3-0:1.0 -> ../../../devices/platform/fe3e0000.usb/usb3/3-0:1.0/
lrwxrwxrwx 1 root root 0 Sep 16 21:31 3-1 -> ../../../devices/platform/fe3e0000.usb/usb3/3-1/
lrwxrwxrwx 1 root root 0 Sep 16 21:31 3-1:1.0 -> ../../../devices/platform/fe3e0000.usb/usb3/3-1/3-1:1.0/
lrwxrwxrwx 1 root root 0 Sep 16 21:31 3-1:1.1 -> ../../../devices/platform/fe3e0000.usb/usb3/3-1/3-1:1.1/
lrwxrwxrwx 1 root root 0 Sep 16 21:31 3-1:1.2 -> ../../../devices/platform/fe3e0000.usb/usb3/3-1/3-1:1.2/
lrwxrwxrwx 1 root root 0 Mar 15 2023 4-0:1.0 -> '../../../devices/platform/usb@fe800000/fe800000.usb/xhci-hcd.0.auto/usb4/4-0:1.0'/
lrwxrwxrwx 1 root root 0 Mar 15 2023 5-0:1.0 -> ../../../devices/platform/fe380000.usb/usb5/5-0:1.0/
lrwxrwxrwx 1 root root 0 Mar 15 2023 6-0:1.0 -> '../../../devices/platform/usb@fe800000/fe800000.usb/xhci-hcd.0.auto/usb6/6-0:1.0'/
lrwxrwxrwx 1 root root 0 Mar 15 2023 7-0:1.0 -> '../../../devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7/7-0:1.0'/
lrwxrwxrwx 1 root root 0 Mar 15 2023 8-0:1.0 -> '../../../devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb8/8-0:1.0'/
lrwxrwxrwx 1 root root 0 Sep 16 22:03 8-1 -> '../../../devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb8/8-1'/
lrwxrwxrwx 1 root root 0 Sep 16 22:03 8-1:1.0 -> '../../../devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb8/8-1/8-1:1.0'/
lrwxrwxrwx 1 root root 0 Mar 15 2023 usb1 -> ../../../devices/platform/fe3a0000.usb/usb1/
lrwxrwxrwx 1 root root 0 Mar 15 2023 usb2 -> ../../../devices/platform/fe3c0000.usb/usb2/
lrwxrwxrwx 1 root root 0 Mar 15 2023 usb3 -> ../../../devices/platform/fe3e0000.usb/usb3/
lrwxrwxrwx 1 root root 0 Mar 15 2023 usb4 -> '../../../devices/platform/usb@fe800000/fe800000.usb/xhci-hcd.0.auto/usb4'/
lrwxrwxrwx 1 root root 0 Mar 15 2023 usb5 -> ../../../devices/platform/fe380000.usb/usb5/
lrwxrwxrwx 1 root root 0 Mar 15 2023 usb6 -> '../../../devices/platform/usb@fe800000/fe800000.usb/xhci-hcd.0.auto/usb6'/
lrwxrwxrwx 1 root root 0 Mar 15 2023 usb7 -> '../../../devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb7'/
lrwxrwxrwx 1 root root 0 Mar 15 2023 usb8 -> '../../../devices/platform/usb@fe900000/fe900000.usb/xhci-hcd.1.auto/usb8'/
如上图所示,可以看到大量的USB
设备。取名规则如下:
bus-port.port:configuration.interface
其中:
bus
:表示USB
控制器所连接的总线编号;从1开始编号;port
:表示总线上的硬件端口号;从0开始编号;port
:如果总线上的硬件端口连接的设备是一个HUB
,那么该port
表示连接在HUB
上的硬件端口号;从1开始编号;configuration
:表示设备的配置值;从1开始编号;interface
:表示设备的接口号;从0开始编号;
比如1-1:1.1
具有以下含义:
1-1
:表示连接到第一个USB
控制器的编号为1的硬件端口;1.1
:表示设备的第一个配置(configuration
)编号为1接口(interface
)。
7-1.2:1.0
具有以下含义:
7-1.2
:表示连接到第7个USB
控制器的编号为1的硬件端口连接了一个HUB
,HUB
编号为2的硬件端口上连接了一个设备;1.0
:表示设备的第一个配置(configuration
)编号为0接口(interface
)。
5.2.2 USB
设备信息
我们可以查看USB
设备PID
和VID
:
root@rk3399:/sys/bus/usb/devices# ls
1-0:1.0 1-1:1.0 2-0:1.0 3-1 3-1:1.1 4-0:1.0 6-0:1.0 8-0:1.0 8-1:1.0 usb2 usb4 usb6 usb8
1-1 1-1:1.1 3-0:1.0 3-1:1.0 3-1:1.2 5-0:1.0 7-0:1.0 8-1 usb1 usb3 usb5 usb7
root@rk3399:/sys/bus/usb/devices# ls 8-1/id*
8-1/idProduct 8-1/idVendor
root@rk3399:/sys/bus/usb/devices# cat 8-1/idVendor
0480
root@rk3399:/sys/bus/usb/devices# cat 8-1/idProduct
b200
root@rk3399:/sys/bus/usb/devices# cat 8-1/manufacturer
TOSHIBA
root@rk3399:/sys/bus/usb/devices# cat 8-1/product
External USB 3.0
root@rk3399:/sys/bus/usb/devices# cat 8-1/version
3.00
VID=0480
、PID=b200
对应的使我们移动硬盘。
1个USB
设备可能会有多个接口,比如:
root@rk3399:/sys/bus/usb/devices# ls 1-1/1-1\:1.
1-1:1.0/ 1-1:1.1/
目录l-1
存放的是USB
设备信息,1-1:1.0
、1-1:1.1
目录下存放的相应接口的信息;
5. 3 debugfs
USB
调试信息位于/sys/kernel/debug/usb
;
root@rk3399:~# ll /sys/kernel/debug/usb
-r--r--r-- 1 root root 0 Jan 1 1970 devices
drwxr-xr-x 4 root root 0 Jan 1 1970 ehci/
drwxr-xr-x 2 root root 0 Jan 1 1970 fe800000.usb/
drwxr-xr-x 2 root root 0 Jan 1 1970 fe900000.usb/
drwxr-xr-x 2 root root 0 Jan 1 1970 fusb302-4-0022/
drwxr-xr-x 4 root root 0 Jan 1 1970 ohci/
drwxr-xr-x 2 root root 0 Jan 1 1970 tcpm-4-0022/
drwxr-xr-x 2 root root 0 Jan 1 1970 uvcvideo/
drwxr-xr-x 4 root root 0 Jan 1 1970 xhci/
其中:
devices
:该文件列出了当前系统中已连接的USB设备的详细信息;ehci
:该目录包含EHCI
主机控制器接口的调试信息;fe800000.usb
:该目录包含与fe800000.usb
控制器相关的调试信息;fe900000.usb
:该目录包含与fe900000.usb
控制器相关的调试信息。fusb302-4-0022
:该目录包含与fusb302-4-0022
设备相关的调试信息,4位I2C
总线编号,0022为I2C
设备地址;ohci
:该目录包含OHCI
主机控制器接口的调试信息;tcpm-4-0022
:该目录包含与tcpm-4-0022
设备相关的调试信息,4位I2C
总线编号,0022为I2C
设备地址;uvcvideo
:该目录包含与uvcvideo
(USB Video Class
,USB
视频类)驱动程序相关的调试信息;xhci
:该目录包含XHCI
主机控制器的调试信息;
5.3.1 查看工作模式
以USB3.0/2.0 OTG0(DWC3/xHCI)
控制器为例,对应设备节点usbdrd3_0: usb@fe800000
:
root@rk3399:~# ll /sys/kernel/debug/usb/fe800000.usb/
-rw-r--r-- 1 root root 0 Jan 1 1970 link_state
-rw-r--r-- 1 root root 0 Jan 1 1970 lsp_dump
-rw-r--r-- 1 root root 0 Jan 1 1970 mode
-r--r--r-- 1 root root 0 Jan 1 1970 regdump
-rw-r--r-- 1 root root 0 Jan 1 1970 testmode
其中:
link_state
:打印DWC3
的链路状态;regdump
:打印DWC3
控制器的寄存器状态信息;mode
:打印DWC3
的工作模式;testmode
:设置DWC3
进HighSpeed
的测试模式,用于眼图测试;
我们可以查看USB3.0/2.0 OTG0
、USB3.0/2.0 OTG1
控制器的工作模式:
root@rk3399:~# cat /sys/kernel/debug/usb/fe800000.usb/mode # OTG0 对应开发板Type-C/DP接口
otg
root@rk3399:~# cat /sys/kernel/debug/usb/fe900000.usb/mode # OTG1 对应开发板CON5接口
host
5.3.2 查看xhci
root@rk3399:/# ll /sys/kernel/debug/usb/xhci/
drwxr-xr-x 6 root root 0 Jan 1 1970 xhci-hcd.0.auto/
drwxr-xr-x 6 root root 0 Jan 1 1970 xhci-hcd.1.auto/
root@rk3399:/# ll /sys/kernel/debug/usb/xhci/xhci-hcd.0.auto/
drwxr-xr-x 2 root root 0 Jan 1 1970 command-ring/
drwxr-xr-x 2 root root 0 Jan 1 1970 devices/
drwxr-xr-x 2 root root 0 Jan 1 1970 event-ring/
drwxr-xr-x 4 root root 0 Jan 1 1970 ports/
-r--r--r-- 1 root root 0 Jan 1 1970 reg-cap
-r--r--r-- 1 root root 0 Jan 1 1970 reg-ext-dbc:00
-r--r--r-- 1 root root 0 Jan 1 1970 reg-ext-legsup:00
-r--r--r-- 1 root root 0 Jan 1 1970 reg-ext-protocol:00
-r--r--r-- 1 root root 0 Jan 1 1970 reg-ext-protocol:01
-r--r--r-- 1 root root 0 Jan 1 1970 reg-op
-r--r--r-- 1 root root 0 Jan 1 1970 reg-runtime
5.3.3 查看ehci
root@rk3399:/# ll /sys/kernel/debug/usb/ehci/
drwxr-xr-x 2 root root 0 Jan 1 1970 fe380000.usb/
drwxr-xr-x 2 root root 0 Jan 1 1970 fe3c0000.usb/
root@rk3399:/# ll /sys/kernel/debug/usb/ehci/fe380000.usb/
-r--r--r-- 1 root root 0 Jan 1 1970 async
-r--r--r-- 1 root root 0 Jan 1 1970 bandwidth
-r--r--r-- 1 root root 0 Jan 1 1970 periodic
-r--r--r-- 1 root root 0 Jan 1 1970 registers
5.3.4 查看fusb302-4-0022
root@rk3399:/# ll /sys/kernel/debug/usb/fusb302-4-0022/
-r--r--r-- 1 root root 0 Jan 1 1970 log
root@rk3399:/# cat /sys/kernel/debug/usb/fusb302-4-0022/log
[ 3.588457] sw reset
[ 3.589715] fusb302 device ID: 0x81
[ 3.591218] pd := off
[ 3.591222] vbus is already Off
[ 3.591225] charge is already Off
[ 3.591228] vconn is already Off
[ 3.591588] pd header := Sink, Device
[ 3.591658] cc1=Open, cc2=Open
[ 3.593266] pd := off
[ 3.593278] vbus is already Off
[ 3.593283] charge is already Off
[ 3.593288] vconn is already Off
[ 3.593623] pd header := Sink, Device
[ 3.593646] cc := Open
[ 3.696903] start drp toggling
[ 3.697640] IRQ: 0x80, a: 0x00, b: 0x00, status0: 0x83
[ 3.697650] IRQ: VBUS_OK, vbus=On
[ 3.698289] IRQ: 0x80, a: 0x00, b: 0x00, status0: 0x83
[ 3.698298] IRQ: VBUS_OK, vbus=On
5.3.5 查看tcpm-4-0022
root@rk3399:/# ll /sys/kernel/debug/usb/tcpm-4-0022/
-r--r--r-- 1 root root 0 Jan 1 1970 log
root@rk3399:/# cat /sys/kernel/debug/usb/tcpm-4-0022/log
[ 3.589722] Setting usb_comm capable false
[ 3.591231] Setting voltage/current limit 0 mV 0 mA
[ 3.591241] polarity 0
[ 3.591297] Requesting mux state 0, usb-role 0, orientation 0
[ 3.591601] state change INVALID_STATE -> SNK_UNATTACHED [rev1 NONE_AMS]
[ 3.591661] CC1: 0 -> 0, CC2: 0 -> 0 [state SNK_UNATTACHED, polarity 0, disconnected]
[ 3.591669] 4-0022: registered
[ 3.591681] Setting usb_comm capable false
[ 3.593293] Setting voltage/current limit 0 mV 0 mA
[ 3.593312] polarity 0
[ 3.593318] Requesting mux state 0, usb-role 0, orientation 0
[ 3.593641] cc:=0
[ 3.595138] pending state change PORT_RESET -> PORT_RESET_WAIT_OFF @ 100 ms [rev1 NONE_AMS]
[ 3.695257] state change PORT_RESET -> PORT_RESET_WAIT_OFF [delayed 100 ms]
[ 3.695272] state change PORT_RESET_WAIT_OFF -> SNK_UNATTACHED [rev1 NONE_AMS]
[ 3.695282] Start toggling
[ 3.697687] VBUS
5.4 更改USB3.0/2.0 OTG
工作模式
我们使用的开发板USB3.0 Type-C PHY1
物理接口被设计为USB3.0 Host Type-A
,这里我们做一个尝试,尝试将USB3.0/2.0 OTG1
控制器工作模式也设置为otg
(同时支持主机/设备)。
Rockchip
官方手册介绍中描述到:USB Gadget driver
内核架构只支持一个USB
控制器配置为otg
,这里我们测试一下看看能不能同时将USB3.0/2.0 OTG0
、USB3.0/2.0 OTG1
控制器都配置为otg
模式;
5.4.1 修改usbdrd_dwc3_1
设备节点
修改arch/arm64/boot/dts/rockchip/rk3399-evb.dts
设备节点usbdrd_dwc3_1
设备节点:
&usbdrd_dwc3_1 {
/* 配置dr_mode为otg */
dr_mode = "otg";
status = "okay";
};
5.4.2 测试
重新编译烧录内核并烧录,查看USB3.0/2.0 OTG0
、USB3.0/2.0 OTG1
控制器的工作模式;
root@rk3399:~# cat /sys/kernel/debug/usb/fe800000.usb/mode # OTG0 对应开发板Type-C/DP接口
otg
root@rk3399:~# cat /sys/kernel/debug/usb/fe900000.usb/mode # OTG1 对应开发板CON5接口
otg
更改工作模式为Host
(主机),这种做法只会临时有效:
root@rk3399:/lib/modules/6.3.0# echo host > /sys/kernel/debug/usb/fe800000.usb/mode
root@rk3399:/lib/modules/6.3.0# echo host > /sys/kernel/debug/usb/fe900000.usb/mode
然后将开发板CON5
、Type-C/DP
这两个接口接上USB
设备测试发现USB
设备均无法正常工作,因此这里我又将usbdrd_dwc3_1
的dr_mode
属性改回为otg
。
参考文章
[1] PD
快充 - fusb302
驱动调试笔记
[2] RK3399 Android7.1 USB
模块中的控制器和PHY
[3] RK3399ANDROID7.1 USB TYPE-A
的配置
[4] 超详细USB Type-C
引脚信号及PCB
布局布线介绍
[5] Rockchip_Developer_Guide_USB_CN.pdf
[6] Rockchip_RK3399_Developer_Guide_USB_DTS_CN.pdf
[7] RK
平台如何配置USB
功能
[8] 正点原子视频
[9] USB
总线-Linux
内核USB3.0
设备控制器之dwc3 gadget
驱动初始化过程分析(五)
[10] ipkvm
之RK3568 usb gadget
[11] linux usb gadget hid
模拟鼠标键盘configfs
[12] LINUX
嵌入式模拟键盘 2022-05-21
[13] usb hid gadget
驱动
[14 ] RK3399
驱动开发 | 18 - 使用usb3.0
作为device
模拟u
盘
[15] linux driver probe deferral
机制
[16] usb gadget configfs
验证
[17] 6.61、USB
如何模拟HID
设备