前些时候做了一个项目,其中要实现USB的功能,包括U盘的读写和使用USB鼠标键盘。经过一段时间的调试终于完工了。现在将一些关键的调试点记下来,一方面大概整理一下自己思路,另一方面希望能给正在做类似工作的兄弟们一些参考,希望对大家能有所帮助。
我的系统是linux 2.6,USB的主控制器采用了爱普生的S1R72V17,USB的驱动代码由爱普生公司提供。在开始工作之前,我先从爱普生的网站上下载了相关的资料,包括这款芯片的datasheet和硬件设计文档以及软件移植文档。
(资料下载网址:http://www.epson.jp/device/semicon_e/product/interface/index.htm)
在这个项目的过程中,我的主要工作是完成硬件的设计和调试,并且将爱普生提供的linux 2.6的驱动移植到我的系统中。
USB的硬件系统设计比较简单(参考下图),通过地址数据总线和CPU相连,另外USB控制器有一个中断信号要接入CPU系统。S1R72V17需要3个不同的电压分别是3.3v, 1.8v和5v。另外一部分电路是关于USB的接口电路,包括差分信号线对和过流保护电路。除此之外72v17还需要一个时钟,这个时钟可以由12M的晶体提供也可以由24M或者48M的有源晶振提供。 http://space.**/upload/2008/7/22/d649d836-ed9d-4ad3-b9ca-504a7b7dc05f.JPG 在硬件电路设计过程中,比较关键的是总线的接法以及差分信号线对的走线。72V17有3种总线访问模式,分别是8bits模式、16bits BE模式以及16bits strobe模式,BE模式需要CPU端提供WBEL和WBEH信号来分别访问高低字节,strobe模式需要CPU端提供WRH和WRL信号来分别访问高低字节。差分信号线对的布线需要注意以下几点:
1> 差分阻抗90欧
2> DM/DP尽量短,使得信号传输延时保持在1ns以下
3> 两条线必须平行,并且等长
4> 这两条线下面的PCB层,必须是整块地,不能有分割
5> 避免在这两条线附件走线。尤其是高速信号和时钟信号要远离这对线
6> 如果不能一直走直线,那么可以在拐点出走弧线,以减小信号反射
7> VBUS线必须远离DP/DM
8> 如果信号线有分叉或者线上有其它器件接入,一定要确保匹配的阻抗
9> 信号线上不要打过孔
10> 推荐使用防静电和浪涌的保护器件
爱普生的网站上提供了72V17在linux2.6.14下的驱动代码,以及相应的移植手册。由于我的系统恰好就是2.6.17的版本,加上驱动说明手册比较详细,所以软件移植上去没有费太大力气。其中比较关键的是寄存器访问,其它的只要按照移植手册设置就可以了。 http://space.**/upload/2008/7/22/47efd230-53c5-41f1-a89b-5ba6758bf6a9.JPG 上图是linux下的USB系统的结构框图,USB core 和Class层不需要做改动,而爱普生提供的驱动代码就是usb host controller driver层。
下面是驱动文件的说明: http://space.**/upload/2008/7/22/f94ab2ee-d83d-4b66-bce6-b0c26999d614.JPG 软件的移植工作量并不大,首先需要改动USB的makefile和kconfig。
在driver/usb/host/Kconfig中加入下面配置
Config USB_V17_HCD
tristate “S1R72V17 HCD support”
depends on USB
default Y
在driver/usb/Makefile中加入下面的内容
obj-$(CONFIG_USB_V17_HCD)+=host/
obj-$(CONFIG_USB_V17_HCD)+=s1r72v17-hcd.o
接着需要改动系统配置,在arch/arm/mach-s3c2410/mach-star.c中加入
//for EPSON Start
static struct resource s1r72xxx_ohci_resources[] = {
[0] = {
.start = 0x28000000,
.end = 0x2c000000,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_EINT5,
.end = IRQ_EINT5,
.flags = IORESOURCE_IRQ,
},
};
static u64 v17_dma_mask = 0xffffffffUL ;
static struct platform_device epson_ohci_device = {
.name = "s1r72v17",
.id = -1,
.dev = {
.dma_mask = &v17_dma_mask,
.coherent_dma_mask = 0xffffffffUL,
},
.num_resources = ARRAY_SIZE(s1r72xxx_ohci_resources),
.resource = s1r72xxx_ohci_resources,
};
//for EPSON End
最后要对Linux系统进行配置,使用make menuconfig进行如下配置。
HCD driver
Device Drivers ->
USB support ->
<*> V17_HCD support.
<*> USB Mass Storage support
<>USB Human Interface Device (full HID) support
USB HID Boot protocol driver -> <*> USB HIDBP keyboard(simple boot) support
<*> USB HIDBP Mouse (simple boot) support
Device Driver ->
Block devices
<*> Low Performance USB Block driver
http://space.**/upload/2008/7/22/a9509abc-33fb-42f4-8a11-389ab8137e1f.JPG
如果寄存器访问没有问题的话就可以进行编译了。
OK! 将编译好的image文件下到板子上,系统的USB功能就实现了。插上U盘试一试,超级终端将会出现下面的信息。
bash-2.05a# hub.c: USB new device connect on bus1/1, assigned device number 2 usb_get_device_descriptor!!!
scsi0 : SCSI emulation for USB Mass Storage devices
Vendor: Generic Model: USB Flash Drive Rev: %z!Y
Type: Direct-Access ANSI SCSI revision: 02
Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0 SCSI device sda: 254720 512-byte hdwr sectors (130 MB)
sda: Write Protect is off
Partition check:
sda:<7>usb-storage: queuecommand() called
sda1 sda2 sda3 sda4
使用mount就可以对U盘进行读写了。除此之外USB鼠标和USB键盘也可以工作。 |