ZYNQ学习之路——USB总线学习(一)

本文转载自:亦梦云烟的博客

通用串行总线(Universal Serial Bus)是连接计算机系统与外部设备的一种串行总线标准,也是一种输入输出接口的技术规范,被广泛地应用于个人电脑和移动设备等信息通信产品。USB总线是最复杂的总线之一,但其广泛使用。本文首先直接使用USB相关的驱动的应用,后面再具体开始编程做自己的USB驱动程序。

一.USB概要
1.1 USB的发展历程
USB1.0最早是在1996年出现,速度只有1.5Mb/s,后经多次发展升级,目前使用广泛的是USB2.0以及USB3.0,最新的USB3.1与USB3.2也在普及中,各版本性能如下表所示:

1.2 电气性能
USB2.0及以下版本采用四线通信,如图1-1所示:

图1-1: USB电缆模型图

其中ID数据线没有画出,只有在OTG功能中才会使用ID这个信号。USB电缆的4根线在USB接口中有固定不变的数字编号以及不同的颜色,这位电缆的识别和使用提供了方便,下表列出了这些数字和颜色规定。

USB3.0向下兼容USB2.0所需要的Vbus,D-,D+和GND四个引脚外,还新增了两组差分导线,加上一组屏蔽线。新增的双差分线用于超速数据传输,新增的屏蔽线作为屏蔽线终端,用于处理信号中断和电子干扰。USB 3.0 Standard-A引脚分配如下:

其中ID数据线没有画出,只有在OTG功能中才会使用ID这个信号。USB电缆的4根线在USB接口中有固定不变的数字编号以及不同的颜色,这位电缆的识别和使用提供了方便,下表列出了这些数字和颜色规定。

USB3.0向下兼容USB2.0所需要的Vbus,D-,D+和GND四个引脚外,还新增了两组差分导线,加上一组屏蔽线。新增的双差分线用于超速数据传输,新增的屏蔽线作为屏蔽线终端,用于处理信号中断和电子干扰。USB 3.0 Standard-A引脚分配如下:

二. Gadget介绍
Linux-USB Gadget驱动框架实现了USB协议定义的设备端的软件功能。Gadget框架提出了一套标准API,在底层,USB设备控制器(USB DeviceController,UDC)驱动则实现这一套API,不同的UDC需要不同的驱动,基于API,Gadget驱动实现了一套硬件无关的功能,这基本可以对应到USB协议里的各种USB Class。

基于底层提供的资源,Gadget驱动可以运行在各种硬件平台上。重要的驱动有:

Gadget Zero,类似于dummyhcd,该驱动用于测试udc驱动。它会帮助您通过USB-IF测试。

Ethernet over USB,该驱动模拟以太网网口,它支持多种运行方式:

CDC Ethernet: usb规范规定的CommunicationsDevice Class “Ethernet Model” protocol。

CDC Subset:对硬件要求最低的一种方式,主要是 Linux 主机支持该方式。

RNDIS:微软公司对CDCEthernet的变种实现。

File-backed Storage Gadget最常见的U盘功能实现。

Serial Gadget实现,包括:

Generic Serial实现(只需要Bulk-in/Bulk-out端点+ep0)

CDC ACM规范实现。

Gadget Filesystem,将GadgetAPI接口暴露给应用层,以便在应用层实现user modedriver。

MIDI: 暴露ALSA接口,提供recording以及playback功能。

三. USB虚拟串口
ZYNQ7000中有两个USB外设,它们都可以当做OTG功能使用,为了使其变成可以虚拟串口或U盘等USB从设备,需要将USB配置为从设备。

1.1 配置内核
Linux内核提供了Gadget模块,该模块提供了USB的许多通用功能,包括虚拟串口,大容量存储设备等功能。在内核编译时配置其为编译成模块。

在内核文件路径下make menuconfig后,配置选项:

Device Drivers --->
[*]USB support ---> 
    [*]USB Gadget Support ---> 
        [M]USB Gadget Drivers
            ...
            [M]Serial Gadget(with CDC ACM and CDC OBEX support)

保存退出后,编译内核,在/drivers/usb/gadget目录下会生成以下驱动文件:

g_serial.ko, libcomposite.ko, usb_f_acm.ko, usb_f_obex.ko, usb_f_serial.ko, u_serial.ko.

配置设备树,设置USB0为从设备模式,将原来的dr_mode="host"更改为:

dr_mode="peripheral":
&usb0 {
	status = "okay";
	dr_mode = "peripheral";
	phy_type = "ulpi";	
};

生成新的设备树devicetree.dtb文件。

1.2 加载模块并测试
将编译好的内核,设备树文件放入SD卡,并启动Linux,按顺序加载前面生成的驱动模块:

Z-turn# insmod u_serial.ko
Z-turn# insmod libcomposite.ko
Z-turn# insmod usb_f_serial.ko
Z-turn# insmod usb_f_obex.ko
Z-turn# insmod usb_f_acm.ko
Z-turn# insmod g_serial.ko
g_serial gadget: Gadget Serial v2.4
g_serial gadget: g_serial ready
zynq-udc: bind to driver g_serial
Z-turn# g_serial gadget: high-speed config #2: CDC ACM config
g_serial gadget: high-speed config #2: CDC ACM config

输出上述信息表示加载模块成功。此时打开设备文件发现多了/dev/ttyGS0设备,这个就是虚拟的串口设备。连接USB数据线到电脑,发现设备管理器中增加了一个串口设备(ELMO GMAS(COM14))。WIN7和WIN10会自动加载基于udc标准的串口驱动,即免驱。

打开串口调试助手,在ZYNQ终端中输入发送测试命令:

Z-turn# echo hello > /dev/ttyGS0

在串口调试助手中可以收到hello\r\n

在ZYNQ终端输入串口接收命令:

Z-turn# cat /dev/ttyGS0

在串口调试助手中输入:hello\n,则ZYNQ终端中可以收到hello。

注:在终端中发送与接收串口数据都是以'\n'为终止条件,即发送的数据会追加'\n',接收的数据必须在收到'\n'时回显。

四. USB虚拟U盘
在调试Linux系统时,我们经常需要修改SD卡中的文件,更新文件系统或者Linux内核、设备树等文件,需要实现通过USB数据线与PC连接,作为PC的存储设备,PC可以直接拷贝文件到开发板中,或者把开发板中的文件通过USB数据线拷贝到PC端,实现数据交互。本文办卡采用Linux3.15内核,ZYNQ7010处理器。

1.1 配置内核
在内核文件路径下make menuconfig后,配置选项:

Device Drivers --->
[*]USB support --->
    [*]USB Gadget Support --->
        [M]USB Gadget Drivers
            ...
            [M]Gadget Filesystem
            [M]Mass Storage Gadget

编译内核后,在/drivers/usb/gadget中生成了g_mass_storage.ko文件,把这个文件复制到开发板中。

1.2 PC识别开发板的SD卡
在嵌入式Linux系统中,SD卡在系统中识别为/dev/mmcblk0,如果有多个分区则每个分区分别是/dev/mmcblk0p1,/dev/mmcblk0p2等,将SD卡目录挂载到PC中进行读写的方法如下:

在终端中执行命令:

Z-turn# modprobe g_mass_storage file=/dev/mmcblk0 removable=1

该命令加载了gadget msc驱动,传递SD卡位模块参数。连接USB数据线到PC,这时在PC端识别了SD卡所有分区,FAT32格式的分区可以显示内容,对于SD卡的ext4,ext3等文件系统无法在windows中显示,只显示一个盘符。此时可以通过USB数据线读写SD卡了。

如果只需要挂载一个分区,修改file参数即可:

Z-turn# modprobe g_mass_storage file=/dev/mmcblk0p1 removable=1

1.3 PC识别开发板的内存文件系统(Ramdisk)
首先创建一个50M的内存文件:

Z-turn# dd if=/dev/zero of=/dev/50M bs=1M count=50

加载Gadget相关的模块:

Z-turn# modprobe g_mass_storage file=/dev/50M removable=1

加载模块后在windows中弹出是否格式化新增的盘符,格式化为FAT格式,往该盘符中添加文件,在Linux中将/dev/50M挂载到/mnt目录下,查看/mnt目录可以发现添加的文件在其中。

图1-1: PC识别Linux中文件为U盘

需要注意的是,该文件系统是RAMDISK文件系统,系统重启后所有的数据内容会丢失。

五. 使用USB共享网络
使用USB来共享网络可以不需要连接路由器,减少开发设备。

配置内核:

Device Drivers --->
[*]USB support --->
    [*]USB Gadget Support --->
        [M]USB Gadget Drivers
            ...
            [M]Ethernet Gadget(with CDC Ethernet support)
            [*]  RNDIS support

如下图所示:

图3-1: 配置RNDIS共享USB网络

还需要配置RNDIS模块,其位于:

Device Driver--->
    Network device support
        USB Network Adapters
            [*]Multi-purpose USB Networking Framework
                HOST for RNDIS and ActiveSync devices

编译内核后,rndis_hos.ko的路径为/drivers/net/usb/rndis_host.ko

最新文章

最新文章