USB驱动实现一个标准的Linux驱动接口到CHIPIDEA的USB Host/OTG控制器。USB提供一个PC到外设的通用交互链路。它支持即插即用,端口扩展,任一种USB外设都使用相同的接口。CHIPIDEA USB控制器兼容EHCI。


配置指南
您可以通过内核配置选项来管理USB OTG和USB器件支持。

OTG support (CONFIG_USB_OTG)
ChipIdea Highspeed Dual Role Controller (CONFIG_USB_CHIPIDEA)
ChipIdea device controller (CONFIG_USB_CHIPIDEA_UDC)
Freescale MXS USB PHY support (CONFIG_USB_MXS_PHY)
USB Gadget support (CONFIG_USB_GADGET)

这些在CC6默认的内核配置文件中都是默认内嵌开启的。 USB设备驱动根据所定选工作的USB器件(USB gadget)驱动来提供各种功能。USB器件驱动实现一个或多个功能,每个提供一种不同的能力。下面这些器件驱动在默认内核配置文件中是支持并作为可加载模块。

Mass Storage Gadget (CONFIG_USB_MASS_STORAGE)
Ethernet Gadget with CDC Ethernet support (CONFIG_USB_ETH)
Serial Gadget with ACM and CDC OBEX support (CONFIG_USB_G_SERIAL)

器件驱动作为可加载模块是因为同时只允许使用一种器件功能。在使用一种器件驱动时,你首先要确保没有加载其它器件驱动。
平台驱动映射表
I.MX6 USB设备驱动位于 drivers/usb/.

File                Description
chipidea/core.c	Chipidea IP core driver
chipidea/udc.c	Chipidea peripheral driver
chipidea/ci_hdrc_imx.c	i.MX glue layer
chipidea/usbmisc_imx.c	i.MX SoC abstract layer
chipidea/otg.c	Chipidea OTG driver
chipidea/otg_fsm.c	Chipidea OTG HNP and SRP driver
phy/phy-mxs-usb.c	i.MX USB physical driver

设备树绑定和定制

  • USB设备定义
    • 通用 i.MX6 设备树
usbotg: usb@02184000 {
        compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
        reg = <0x02184000 0x200>;
        interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&clks IMX6QDL_CLK_USBOH3>;
        fsl,usbphy = <&usbphy1>;
        fsl,usbmisc = <&usbmisc 0>;
        fsl,anatop = <&anatop>;
        status = "disabled";
};
  • IOMUX 配置
    • ConnectCore 6 核心板设备树
usbotg {
        pinctrl_usbotg: usbotg {
            fsl,pins = <
                MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
                MX6QDL_PAD_EIM_D22__USB_OTG_PWR 0x17059
                MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x17059
            >;
        };
};
  • USB 设备启用和定义
    • ConnectCore 6 SBC 设备树
&usbotg {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usbotg>;
        fsl,power-line-polarity-active-high;
        fsl,over-current-polarity-active-low;
        status = "okay";
};

USB设备驱动通过/dev/bus/usb来表现连接的设备,该接口能表现不同的USB设备相关器件功能。

串口器件(Serial Gadget)

串口器件表现为一种TTY串行接口,可以使用minicom或类似工具。多数的Linux主机可以用通用usb转串口驱动和这样的接口交互。

加载串口器件驱动模块 细节请参考Documentation/usb/gadget_serial.txt:

目标核心板:

# modprobe g_serial
Connect the target platform to a Linux host computer via the USB cable. Linux will create a device node called /dev/ttyGS0 on the target side and a device node called /dev/ttyACM0 on the host side. (Node names may vary in different distributions.)
The USB connection between target and host now works as a serial line.
Testing the serial gadget

You can verify the serial connection of the two ports:
Configure the serial port of the host computer:
Host PC
$ stty -F /dev/ttyACM0 raw -echo -echoe -echok -echoctl -echoke
Configure the serial port of the target platform:
Target device
# stty -F /dev/ttyGS0 raw -echo -echoe -echok -echoctl -echoke
On the host, read the contents arriving at the new serial port:
Host PC
$ cat /dev/ttyACM0
On the target, write a text line to the serial port:
Target device
# echo "Hello from target side" > /dev/ttyGS0
You will see the text line arrive at the host computer.
Opening a console shell via USB serial

The following instructions describe how to open a console shell via the USB serial port.
On the target side, execute a console on the serial gadget with the getty command (baudrate is mandatory but irrelevant):
Target device
# setsid getty -L -l /bin/sh -n 115200 /dev/ttyGS0
The setsid command avoids permission problems when running getty from an interactive shell.
On the host side, open a minicom or putty session on the USB serial port /dev/ttyACM0 to access the shell.
 
Settings like speed or parity for the serial terminal session (and for the getty command) are irrelevant, as the communication takes place at USB speed. The serial communication settings are emulated.
Unloading the serial gadget

To unload the USB serial gadget from the system:
Target device
# rmmod g_serial
# rmmod usb_f_acm
# rmmod libcomposite

暂无内容

大容量存储器件功能(mass-storage gadget)

通过大容易存储器件的功能,核心板平台表现在主机上是枚举为一个SCSI硬盘驱动器。一个文件或块设备可以作为驱动器的存贮器。

使用文件作为存贮器

创建一个存贮器文件

您需要在器件使用它之前创建存贮器文件。存贮器文件是一个创建为所需全部容量大小的正规文件。只需创建一次,在加载器件驱动之前需要完成所有创建工作。下面这个例子演示了如何在核心板root目录下创建128M大小的存贮文件。

核心板上:

# dd bs=1M count=128 if=/dev/zero of=/backing_file
128+0 records in
128+0 records out
给存贮器分区

创建好存贮器文件就像拥有了一块全新磁盘,在使用它之前您需要创建分区和文件系统。 使用fdisk程序来给存存贮器文件分区并指定柱面(Cylinder),磁头(Head),扇区(Sector)等参数。这些参数值是任意的,但存储器件驱动使用每扇区512字节,所以公式是:

512 * Cylinders * Heads * Sectors = 存贮文件总字节数

比如128 MiB存贮文件, 我们可以用下面值: Cylinders = 32 Heads = 16 Sectors = 512 也就是 512*32*16*512 = 128 MiB 在核心板上我们运行fdisk,使用CHS参数来给存贮文件分区: 核心板上:

# fdisk -C 32 -H 16 -S 512 /backing_file
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel. Changes will remain in memory only,
until you decide to write them. After that the previous content
won't be recoverable.
Command (m for help):

这里是交互命令区,可以按m查看所有命令,要在整个存贮文件内创建主分区,完整操作过程如下: 按n新建个分区. 随后按p表示要新建主分区 按1来指定分区号 后面两项直接回车,选择默认值,表示用首个柱面和最后一个柱面,也就是全部的空间 核心板上:

Command (m for help): n
Command action
    e   extended
    p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-260, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-260, default 260):
Using default value 260

新分区默认是Linux的ext4格式分区,想改变为FAT32,按如下方式操作: 按t选择类型 只有一个分区,默认是分区1被选中 按b选择Windows 95的FAT32文件系统 核心板上:

Command (m for help): t
Selected partition 1
Hex code (type L to
list codes): b
Changed system type of partition 1 to b (Win95 FAT32)

按p打印分区表,检查一下 核心板上:

Command (m for help): p
Disk backing_file: 134 MB, 134217728 bytes
16 heads, 63 sectors/track, 260 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes
 
       Device Boot      Start         End      Blocks  Id System
backing_file1               1          260     131008+  b Win95 FAT32

按w把上面的分区写入到存贮文件中 核心板上:

Command (m for help): w
The partition table has been
altered!
 
Calling ioctl() to re-read partition table.
fdisk: WARNING:rereading partition table failed, kernel still uses old table: Inappropriate
ioctl for device

到这一步,分区已经创建好,但它并没有任何文件在里面。最简单的方法来创建文件系统加载驱动,能过USB线缆连接到主机,然后在主机里创建相关的文件。

加载大容量存储器件驱动模块

核心板上:

# modprobe g_mass_storage file=/backing_file stall=no
# dmesg
...
LUN: removable file: (no medium)
Number of LUNs=1
LUN: file: /backing_file
Number of LUNs=1
g_mass_storage gadget: Mass Storage Gadget, version: 2009/09/11
g_mass_storage gadget: userspace failed to provide iSerialNumber
g_mass_storage gadget: g_mass_storage ready
g_mass_storage gadget: high-speed config #1: Linux File-Backed Storage

当您连上核心板和主机,可以通过dmesg查询,看到上面的信息就在打印出来。 接下来就可以用主机来对这个磁盘进行操作了,比如格式化,拷贝文件。 创建并加载文件系统

Linux主机

Linux主机会把核心板当作一个新的SCSI设备,并分配设备名为sdx,其中x是字母索引,分区则会展示为sdx1。要查看主机分配的设备名,请用下面命令打印系统log: 电脑主机上:

$ dmesg
usb 2-1.1: new high-speed USB device number 10 using ehci_hcd
usb-storage 2-1.1:1.0: Quirks match for vid 0525 pid a4a5: 10000
scsi9 : usb-storage 2-1.1:1.0
usb 2-1.3: USB disconnect, device number 3
scsi 9:0:0:0: Direct-Access     Linux    File-Stor Gadget 0314 PQ: 0 ANSI: 2
sd 9:0:0:0: Attached scsi generic sg2 type 0
sd 9:0:0:0: [sdb] 262144 512-byte logical blocks: (134 MB/128 MiB)
sd 9:0:0:0: [sdb] Write Protect is off
sd 9:0:0:0: [sdb] Mode Sense: 0f 00 00 00
sd 9:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
sdb: sdb1
sd 9:0:0:0: [sdb] Attached SCSI disk

在本例中,主机分配sdb1作为存贮器设备节点的分区。 在主机上,在该分区创建一个vfat文件系统(您可能需要root权限): 在电脑主机端格式化设备时,注意不要把你硬盘对应的设备格式化,以免造成损失。 电脑主机上:

$ mkfs.vfat -F 32 /dev/sdb1

现在,在主机上加载该设备以便有读写权限。如果您的主机桌面系统支持自动加载设备,您可以断开USB再连接,这样就不用打命令了。 手动加载操作如下,您可能需要root权限。 电脑主机上:

$ mkdir /media/usbdisk
$ mount /dev/sdb1 /media/usbdisk -t vfat

上面这个例子我们加载设备到/media/usbdisk。现在我们可以创建文件或文件夹了。如果您需要把USB作为其它设备,移除USB线之前请卸载该设备文件夹。 电脑主机上:

$ umount /media/usbdisk

Windows主机

Windows电脑会会认出一个全新的U盘,并通知您该磁盘没有格式化,按提示使用工具进行格式化,其它操作和U盘无区别。 An MS-Windows host computer recognizes the target as a new USB mass storage device. A warning message appears to inform

从核心板访问存贮文件空间

要从板子上访问存贮空间,请不要在核心板已经连接到一个USB主设备(比如电脑)时尝试这么做。关键是用losetup程序配合“-o”偏移选项来设置环路设备驱动。要使这正常工作,您需要知道分区的偏移量,用下面的方法获取:

#fdisk -lu /backing_file 

注意start的值,也就是起始扇区,这个值乘以每扇区字节数就是起始的偏移量。

offset偏移量=63*512=32256 Byte 在linux系统中,/dev/loop(或称vnd (vnode disk)、lofi(循环文件接口))是一种伪设备,这种设备使得文件可以如同块设备一般被访问。在使用之前,循环设备必须与现存文件系统上的文件相关联。这种关联将提供给用户一个应用程序接口,允许文件视为块特殊文件使用。因此,如果文件中包含一个完整的文件系统,那么这个文件就能如同磁盘设备一般被挂载。

#losetup -o 32256 /dev/loop0 /backing_file
#mkdir /mnt/myloop
#mount -t vfat /dev/loop0 /mnt/myloop
#ls /mnt/myloop

不用时要卸载

#umount /dev/loop0

使用区块设备作为存贮器

你也可以使用SD卡或U盘等作为核心板的存贮器。比如,如果我们插入一个带有两个分区的SD卡,您可以用下面命令查出分区名称:

核心板上:

# ls -l /dev/mmc*
brw-rw----    1 root     root     179,   8 Jan  7 22:28 /dev/mmcblk1
brw-rw----    1 root     root     179,   9 Jan  7 22:19 /dev/mmcblk1p1
brw-rw----    1 root     root     179,  10 Jan  7 22:19 /dev/mmcblk1p2

其中mmcblk1是卡,mmcblk1p1和mmcblk1p2是分区。 在核心板上卸载相关磁盘

当使用区块设备作为存贮器件,我们推荐您首先在核心板端卸载相关媒介。否则从主机上和目标板上对它的访问无法同步进行会造成出错。 确保所有分区都卸载提,如: 核心板上

# umount /dev/mmcblk1p1
# umount /dev/mmcblk1p2 

加载大容量存储器件驱动模块

核心板上:

# modprobe g_mass_storage file=/dev/mmcblk1 stall=0
Number of LUNs=8
Mass Storage Function, version: 2009/09/11
LUN: removable file: (no medium)
Number of LUNs=1
LUN: file: /dev/mmcblk1
Number of LUNs=1
g_mass_storage gadget: Mass Storage Gadget, version: 2009/09/11
g_mass_storage gadget: userspace failed to provide iSerialNumber
g_mass_storage gadget: g_mass_storage ready
g_mass_storage gadget: high-speed config #1: Linux File-Backed Storage
Now, when you connect the USB cable to a host computer, the two partitions of the SD card will be accessible from the host.

卸载大容量存储设备驱动模块

# rmmod g_mass_storage
# rmmod libcomposite