i.MX6ULL有两路USB功能接口USB_OTG1和USB_OTG2,这两路USB都支持OTG功能。OTG是On-The-Go的缩写。简单地说,当具备OTG功能的设备(以i.MX6ULL为例)连接到USB主设备(以电脑为例)的时候,i.MX6ULL会识别出它连接的是主设备,于是把自己作为从设备device与电脑通信,不给OTG接口供电;当i.MX6ULL与U盘连接的时候,i.MX6ULL会识别出U盘是device从设备,于是把自己作为host主设备与U盘通信,并给OTG接口供电,为U盘提供电源。这一功能的实现是通过i.MX6ULL检测一个ID引脚的高低电平实现的,还有一个VBUS引脚用于提供电源,当作为device从设备时,VBUS由外部host设备供电;当作为host设备时,VBUS需要串一个5V电源输出给device从设备。
当主设备(如电脑)通过电缆插入插座时,电缆的插头内的ID脚是悬空的,CPU检测到的ID引脚是高电平,同时电脑通过USB电缆将插座的1脚(连接到VBUS)电压提升至5V,CPU就工作在device模式下。
当从设备(如U盘)通过电缆插入插座时,电缆的插头内的ID脚是对地短接的, CPU检测到ID引脚是低电平,CPU就工作在HOST模式,同时通过USB座子1脚(连接到VBUS)为设备端供电。
ELF 1开发板使用TYPE C座将USB_OTG1功能引出,i.MX6ULL通过检测TYPE C类型的插头内的CC引脚线的高低,来判断自己是工作在host模式还是device模式,ELF 1开发板直接将CC(TYPE C座的CC1和CC2还有检测插入方向的功能,这里不展开讲)引脚接地了,并没有连接到SOC检测引脚,所以使用OTG功能,i.MX6ULL只能工作在device模式,当做从设备使用。当然也可以通过修改软件,将此接口用作host模式。
将USB_OTG2作为host使用,接到了USB扩展芯片上,型号FE1.1S,扩展为4路USB,分别连接了2个Type-A插座,蓝牙wifi模块,扩展板的4G模块。
硬件原理
USB OTG功能使用的是OTG专属引脚USB_OTG_P、USB_OTG_N、USB_OTG_VBUS,不需要做mux配置。USB_OTG2连接HUB芯片用于USB扩展,其中HUB芯片有一个HUB_nRST复位功能引脚,由SN74HC595D控制。
IOMUX配置
由于OTG使用的是专属引脚USB_OTG引脚,不需要IOMUX配置。
设备节点
在arch/arm/boot/dts/imx6ull-elf1-emmc.dts文件中已经添加好的配置otg1和otg2的设备节点:
&usbotg1 { /*dr_mode = “otg”;*/ dr_mode = “peripheral”; srp-disable; hnp-disable; adp-disable; status = “okay”; };
&usbotg2 { dr_mode = “host”; disable-over-current; status = “okay”; }; &usbphy1 { tx-d-cal = <0x5>; }; &usbphy2 { tx-d-cal = <0x5>; }; |
一、Usbotg1节点下属性
dr_mode = "peripheral";ELF 1的USB_OTG1只作为device所以,dr_mode更改为peripheral外围接口,即device模式。
srp-disable,hnp-disable,adp-disable,这三个属性都是USB OTG相关协议:
SRP:Session Request Protocol,会话请求协议,此协议对于从设备可选可不选,这里不选。
HNP:Host Negotiation Protocol,主从交换协议,这里只使用从设备,所以可以关闭此协议。
ADP:Attach Detection Protocol,连接检测协议,主要应用于主设备,对于从设备可选可不选,这里不选。
二、Usbotg2节点下属性
dr_mode = "host";USB_OTG2作为host主设备。
disable-over-current;表示不使用过流检测功能。
同网络、CAN一样,USB也需要的phy负责最底层的信号转换,i.MX6ULL内部集成的usb phy。usbphy1和usbphy2分别表示USB_OTG1和USB_PHY2的 phy,tx-d-cal = <0x5>;是调整USB通信信号质量的参数。
当然也使用Usbotg2节点的配置方式,配置Usbotg节点,使USB_OTG1工作在host模式。
除了上述配置之外,还需要注意一下,USB HUB芯片的HUB_nRST复位功能引脚是否已经拉高,该引脚由SN74HC595D芯片的QD引脚控制:
gpio_spi: gpio_spi@0 { compatible = “fairchild,74hc595”; gpio-controller; #gpio-cells = <2>; reg = <0>; registers-number = <1>; registers-default = /bits/ 8 <0xaf>; spi-max-frequency = <100000>; }; |
显然,0xaf值的bit3位已设置为高。
添加驱动
一、配置内核
使用make menuconfig打开图形化配置界面:
elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ make menuconfig |
找到以下路径:
Device Drivers ->USB support ->USB Gadget Support |
二、替换配置文件
通过make menuconfig修改的内容写入到了.config文件,当使用make imx6ull_elf1_defconfig配置内核源码时,.config文件会被覆盖,因此,需要替换原有的imx6ull_elf1_defconfig。
elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ cp .config arch/arm/configs/imx6ull_elf1_defconfig |
编译测试
编译内核、设备树和模块并拷贝到开发板:
elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ ./build.sh elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ scp arch/arm/boot/zImage root@172.16.0.175:/run/media/mmcblk1p1/ elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ scp arch/arm/boot/dts/imx6ull-elf1-emmc.dtb root@172.16.0.175:/run/media/mmcblk1p1/ elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ scp .tmp/rootfs/modules.tar.bz2 root@172.16.0.175:~/ |
在开发板上解压打包好的模块到根目录:
root@ELF1:~# tar -xvf modules.tar.bz2 -C / |
进行sync操作后重启开发板:
USB host:先测试USB host功能,这个测试就比较简单了,直接将U盘插到TYPE A座上,系统就会自动识别到U盘设备,在/dev/下生成sda1节点。
USB device:我们用PC机作为HOST,开发板作为一个device设备,将开发板上的U盘挂载到PC上。
将一个U盘插到板子TYPE A座上,使用另一条TYPE C线连接OTG和PC机:
运行命令:
insmod libcomposite.ko insmod usb_f_mass_storage.ko insmod g_mass_storage.ko file=/dev/sda1 removable=1 |
可看到PC机挂载上了开发板上的U盘。