现在的位置: 首页 > 综合 > 正文

USB-HOST调试纪实

2014年02月25日 ⁄ 综合 ⁄ 共 8045字 ⁄ 字号 评论关闭

Linux下的硬件驱动——USB设备(上)(驱动配置部分)

http://www.ibm.com/developerworks/cn/linux/l-usb/index1.html

Linux下的硬件驱动——USB设备(下)(驱动开发部分)

http://www.ibm.com/developerworks/cn/linux/l-usb/index2.html

关于kernel2.6中USB host controller driver 的问题

 

2.6在s3c2410上usb host不工作的直接结果就是提示110错误: 
usb 1-1: device descriptor read/64, error -110 

追踪错误代码,我们来看看能不能找到导致这个错误的线索。 

include/asm-generic/errno.h 
#define EPROTO 71 /* Protocol error */ 
#define EILSEQ 84 /* Illegal byte sequence */ 
#define ETIMEDOUT 110 /* Connection timed out */ 


Documentation/usb/error-codes.txt 
-EPROTO (*, **) a) bitstuff error 
b) no response packet received within the 
prescribed bus turn-around time 
c) unknown USB error 

-EILSEQ (*, **) a) CRC mismatch 
b) no response packet received within the 
prescribed bus turn-around time 
c) unknown USB error 

-ETIMEDOUT (**) No response packet received within the prescribed 
bus turn-around time. This error may instead be 
reported as -EPROTO or -EILSEQ. 

由此我们可以判断,这个错误与 usb 设备的超时有关。报告这个错误的地方在drivers/usb/core/hub.c中的hub_port_init部分,由于 usb_get_device_descriptor获取 usb 设备信息的时候产生了超时。这样基本可以确定三种情况,1、usb
设备及接口有问题;2、usb core有问题;3、usb driver有问题。 

我们可以很容易地排除1和2的可能性,问题应该在usb driver implement部分造成的。2.6的usb driver把usb规范中对usb接口的操作集中到了core里面,针对不同设备的implement分别归为host、gadget、storage
等。基本确定问题就在ohci-s3c2410.c里。 


跟踪进入ohci-s3c2410.c,这里面主要完成s3c2410 usb host设备的初始化工作,包括电源、时钟、寄存器等。 

其实很多问题在互联网上已经被遇到和解决,我们要做的就是多参考别人的成功经验,这样可以节省时间,同时能够帮助我们找到一些思路。借助google这双强大的翅膀,我们来看看能找到什么: 

http://www.linux-usb.org/FAQ.html#ts6 

Q: Why doesn’t USB work at all? I get “device not accepting address”. 

A: You may have some problem with your PCI setup that’s preventing your USB host controller from getting hardware interrupts. When Linux submits a request, but never hears back from the controller, this is the diagnostic you’ll see. To see if this is the problem,
look at /proc/interrupts to see if the interrupt count for your host controller driver ever goes up. If it doesn’t, this is the problem: either your BIOS isn’t telling the truth to Linux (ACPI sometimes confuses these things, or setting the expected OS to
windows in your BIOS), or Linux doesn’t understand what it’s saying. 

Sometimes a BIOS fix will be available for your motherboard, and in other cases a more recent kernel will have a Linux fix. You may be able to work around this by passing the noapic boot option to your kernel, or (when you’re using an add-in PCI card) moving
the USB adapter to some other PCI slot. If you’re using a current kernel and BIOS, report this problem to the Linux-kernel mailing list, with details about your motherboard and BIOS. 

google返回的大量结果中有个建议是设置old_scheme_first标志,让驱动程序优先处理采用老式结构的设备: 
设置old_scheme_first=y 
测试结果并没有太大帮助,不是这个原因引发的。 

linux-usb-devel mail list 上Ben大哥正在不断更新他的ohci-s3c2410 driver,但好像还没最终完成。 
http://www.mail-archive.com/linux-usb-devel@lists.sourceforge.net/msg33670.html 

跟踪ohci-s3c2410.c,发现to_s3c2410_info返回NULL,很明显,是platform_data没有定义,在 include/asm/arch/usb-control.h中已经有struct s3c2410_hcd_info,那么仿照simtec的usb-simtec.c,来构造自己的platform_data。 

static struct s3c2410_hcd_info smdk2410_usbcfg = { 
.port[0] = { 
.flags = S3C_HCDFLG_USED 
}, 
};
 

然后在smdk2410_init中完成初始化: 

s3c_device_usb.dev.platform_data = &smdk2410_usbcfg; 

重新make zImage,情况有所变化: 
初始化usb controller的过程中有一行debug信息: 
s3c2410-ohci: CTRL: TypeReq=0x2303 val=0x8 idx=0x1 len=0 ==> -115 

include/asm-generic/errno.h中查了一下这个错误代码: 
#define EINPROGRESS 115 /* Operation now in progress */ 

Documentation/usb/error-codes.txt中的解释是: 
-EINPROGRESS URB still pending, no results yet 
(That is, if drivers see this it’s a bug.)
 

这时无论插入什么USB设备,USB鼠标、U盘、USB无线网卡,都报告: 
<6>usb 1-1: new full speed USB device using s3c2410-ohci and address 2 
<7>s3c2410-ohci s3c2410-ohci: urb c3c430c0 path 1 ep0in 5ec20000 cc 5 –> status -110
 

看上去这两个错误应该存在关联,可能前面的115错误导致了后面的110错误;在跟踪过程中发现115错误是在GetPortStatus时产生 的,从这个情况来看,可以暂时屏蔽0hci-s3c2410.c中GetPortStatus的实现部分,继续观察变化,结果还是110错误,因此可以排
除115 造成110错误的假设。 


最后怀疑是时钟设置的问题,便参照2.4.18的代码在clk_enable(clk);后面加了个udelay(11);但是错误还是没有解决。 

那么需要对ohci-s3c2410.c进行详细的排查了,2.6把系统资源进行了详细的分类,这使得驱动程序要完成初始化相应设备寄存器的工 作,查遍 ohci-s3c2410.c,竟然没有对s3c24102410的UPLLCON进行设置的代码,问题很可能就在这里,user
manual说UPLLCON需要48.00MHz output, 于是在s3c2410_start_hc里增加: 


__raw_writel((0x78<<12)|(0x02<<4)|(0x03), S3C2410_UPLLCON); 

OK!usb host可以工作了,但是在第一次上电还会出现110错误,reset后才可以正常,2410上的这个UPLLCON问题由来已久,2.4内核也经常出现,原因是UPLLCON的值没有设置成功,那么就需要对设置的值进行检查,直到成功为止。 

把上面的代码修改为: 
unsigned long upllvalue = (0x78<<12)|(0x02<<4)|(0x03); 

while (upllvalue != __raw_readl(S3C2410_UPLLCON)) 

__raw_writel(upllvalue, S3C2410_UPLLCON); 
mdelay(1); 
}

不需要修改Kconfig和Makefile,把ohci-s3c2410.c放到drivers/usb/host/目录,编辑drivers/usb/host/ohci-hcd.c,翻到末尾处增加以下红色部分代码: 

#ifdef CONFIG_SOC_AU1X00 
#include "ohci-au1xxx.c" 
#endif 

#ifdef CONFIG_ARCH_S3C2410 
#include "ohci-s3c2410.c" 
#endif 


#if !(defined(CONFIG_PCI) \ 
|| defined(CONFIG_SA1111) \ 
|| defined(CONFIG_ARCH_OMAP) \ 
|| defined (CONFIG_ARCH_LH7A404) \ 
|| defined (CONFIG_PXA27x) \ 
|| defined (CONFIG_SOC_AU1X00) \ 
|| defined (CONFIG_ARCH_S3C2410) \ 

#error "missing bus glue for ohci-hcd" 
#endif

经过修改可以找到USB设备,但是无法mount上,已经把文件系统支持编译进内核了,但是还是提示“sda:unknown partition table”,无法mount,这该如何解决呢
使能CONFIG_MSDOS_PARTITION选项

感谢panjet提供的经验,对我很有帮助! 

我按照你的方法在linux 2.6.14内核中加入s3c2410 ohci驱动,现在还有一些问题,请指点一下。 

>然后在smdk2410_init中完成初始化: 
>s3c_device_usb.dev.platform_data = &smdk2410_usbcfg; 
我一直没找到smdk2410_init这个函数,2.6.11的内核也搜索过。请问在哪个文件中? 
目前我把 
s3c_device_usb.dev.platform_data = &smdk2410_usbcfg; 
加在arch/arm/mach-s3c2410/s3c2410.c中的int __init s3c2410_init(void)函数中 

加入了usb massive storage, scsi等支持,编译好内核后下载,U盘的一些信息如下: 
启动信息: 
s3c2410-ohci s3c2410-ohci: S3C24XX OHCI 
s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1 
s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000 
usb usb1: Product: S3C24XX OHCI 
usb usb1: Manufacturer: Linux 2.6.14 ohci_hcd 
usb usb1: SerialNumber: s3c24xx 
hub 1-0:1.0: USB hub found 
hub 1-0:1.0: 2 ports detected 
Initializing USB Mass Storage driver... 
usb 1-1: new full speed USB device using s3c2410-ohci and address 2 
usb 1-1: Product: Solid state disk 
usb 1-1: Manufacturer: USB 
usb 1-1: SerialNumber: 103016D43E4492CA 
scsi0 : SCSI emulation for USB Mass Storage devices 
usbcore: registered new driver usb-storage 
USB Mass Storage support registered. 

OHCI驱动已经支持 

INIT: version 2.86 booting 
Vendor: kpm Model: kpm Rev: 1.11 
Type: Direct-Access ANSI SCSI revision: 02 
SCSI device sda: 129024 512-byte hdwr sectors (66 MB) 
sda: Write Protect is off 
sda: assuming drive cache: write through 
SCSI device sda: 129024 512-byte hdwr sectors (66 MB) 
sda: Write Protect is off 
sda: assuming drive cache: write through 
/dev/scsi/host0/bus0/target0/lun0:<7>usb-storage: queuecommand called 
p1 
Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0 
Attached scsi generic sg0 at scsi0, channel 0, id 0, lun 0, type 0 

U盘信息也已正确识别,并已attach 

bash-3.00# cat /proc/scsi/scsi 
Attached devices: 
Host: scsi0 Channel: 00 Id: 00 Lun: 00 
Vendor: kpm Model: kpm Rev: 1.11 
Type: Direct-Access ANSI SCSI revision: 02 

bash-3.00# cat /proc/scsi/usb-storage/0 
Host scsi0: usb-storage 
Vendor: USB 
Product: Solid state disk 
Serial Number: 103016D43E4492CA 
Protocol: Transparent SCSI 
Transport: Bulk 
Quirks: 

bash-3.00# cat /proc/bus/usb/devices 

T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 
B: Alloc= 0/900 us ( 0%), #Int= 0, #Iso= 0 
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 
P: Vendor=0000 ProdID=0000 Rev= 2.06 
S: Manufacturer=Linux 2.6.14 ohci_hcd 
S: Product=S3C24XX OHCI 
S: SerialNumber=s3c24xx 
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 0mA 
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 
E: Ad=81(I) Atr=03(Int.) MxPS= 2 Ivl=255ms 

T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 
P: Vendor=0ea0 ProdID=6803 Rev= 1.00 
S: Manufacturer=USB 
S: Product=Solid state disk 
S: SerialNumber=103016D43E4492CA 
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA 
I: If#= 0 Alt= 0 #EPs= 3 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage 
E: Ad=81(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms 
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms 
E: Ad=83(I) Atr=03(Int.) MxPS= 2 Ivl=1ms 

上述信息说明U盘已经识别并挂载(我这么认为),应该是可以mount了,但在/dev下我找不到挂载点,如sda,也就没法读U盘的数据。内核 中已经支持了usb massive storage, scsi, msdos partition/
filesystem。 


请问这个问题如何解决? 是不是内核中还需要修改一些配置

搞定了这个问题,没有加入对应文件系统的language编码支持。 
配置如下: 
File systems --> 
DOS/FAT/NT Filesystems --->

  • MSDOS fs support
  • VFAT (Windows-95) fs support 
    (437) Default codepage for FAT 
    (iso8859-1) Default iocharset for FAT 
    Native Language Support --> 
    (iso8859-1) Default NLS Option
  • Codepage 437 (United States, Canada)
  • NLS ISO 8859-1 (Latin 1; Western European Languages



  • 关于smdk2410_init函数的问题,不少网友来信询问,补充如下: 

    通过查看arch/arm/mach-s3c2410/mach-bast.c的 MACHINE_START/MACHINE_END 节我们可以看到有一个 
    .init_machine的成员,可以用来设置用户自定义的初始化信息。 
    而在原始的arch/arm/mach-s3c2410/mach-smdk2410.c中是没有这个成员的,我们可以仿照mach-bast.c加入 
    这个成员,给它传递一个初始化函数的地址。 

    首先在 MACHINE_START/MACHINE_END 节前面的位置这样定义这个初始化函数: 

    抱歉!评论已关闭.