Linux-USB Gadget : Part 5: 测试 PXA UDC 驱动

Linux-USB Gadget : Part 5: 测试 PXA UDC 驱动

作者: zjujoe 转载请注明出处

Email[email protected]

BLOGhttp://blog.csdn.net/zjujoe

 

前言

       USB 协议的特性之一就是把复杂性留给软件。USB 驱动纷繁复杂,不管主机端还是设备端,不管是底层控制器驱动还是上层各种 CLASS 驱动。对于这么复杂的软件族,在测试方面付出一些努力是很有价值的。Linux usb 社团开发了一些测试用例。大概是因为开发控制器驱动的人比较多(因为每个硬件平台都不同),这些测试用例主要用于测试底层控制器驱动。

 

简介

测试的大体原理是这样的,在主机端有 usbtest 内核模块,它是一个专用于测试的 usb 客户驱动, 该某块通过 ioctl 接口提供了各种测试类型, 比如 Simple non-queued bulk I/O tests Queued bulk I/O tests ,等等 (如果您不是很理解,建议您去阅读 fudan_abc 写的Linux 那点事儿系列, 或者您没空,读一下内核相关文档)。在应用层则有一个程序及脚本 (testusb.c and test.sh),用于触发各种测试。对应的,在设备端,有各种gadget 驱动配合测试,比如,g_zero 便是其中之一。这一套流程可以用来测试主机端及外设端的控制器驱动。我们这里并不打算翻译http://www.linux-usb.org/usbtest/index.html(这里提供了测试代码,流程等),我们主要是结合 PXA 平台的测试要求提供一个测试实例 (把自己的实践经验记录下来)。 PXA 平台支持 otg 功能,我们首先测试设备端控制器驱动。

测试过程

1.         首先是准备一台 Linux 主机。 在一台笔记本上安装了 ubuntu 7.10, 并重新编译了内核(如何编? Google 一下),替换掉系统标准内核以及 initramfs 这样, 编译出的模块就可以安装到内核了。

2.         主机端,编译出内核模块 usbtest。并安装到内核。大体查看一下, 该模块提供了10几个 testcase:

0)       空操作

1)       Simple non-queued Bulk out

2)       Simple non-queued Bulk in

3)       Simple non-queued Bulk out, vary size

4)       Simple non-queued Bulk in, vary size

5)       等等。

id_table 可以看到, 它支持各种 usb device, 我们在 device 端使用 g_zero, 也包含在这里面。

3.         主机端,安装内核模块: modprobe usbtest

4.         主机端,安装 usbfs: mount -t usbfs none /proc/bus/usb,这样 /proc/bus/usb 下就会列出  usb 的设备信息,我们的测试程序依赖这些信息。

5.         主机端,编译出 testusb: gcc -Wall -g -lpthread -o testusb testusb.c

6.         设备端, 安装 g_zero 驱动: insmod g_zero.ko

7.         主机端,开始测试, testusb –a

8.         发现执行出错,设备端报错:

bad OUT byte, buf [0] = 22

使用 KFT Graphviz 工具,得到函数调用关系图:

 

Linux-USB Gadget : Part 5: 测试 PXA UDC 驱动_第1张图片

 

原来zero_setup 中在 set interface 时会先调用 zero_reset_config 而该函数会间接调用到complete 函数: source_sink_complete。该函数本来是在从主机端传来数据时调用,其中会检查数据有效性。 现在调用,buffer 里只有无效数据, 所以出错。

zero_setup 中对 zero_reset_config 函数的调用注释掉。

9.         继续测试,发现到 test case 10 时出错. 跟踪 usbtest.c, 发现函数 ctrl_out 中有如下语句:

          1251         if (length < 1 || length > 0xffff || vary >= length)

testusb 中,length very 缺省值均为512. 于是直接出错返回。

10.     不再使用缺省值测试, 发现:

./testusb -a -c10 -t10 -s512 -g16 -v32

可以正常通过。.

11.     现在usbtest 可以基本跑起来, 不过比较脆弱。每个 test case 都能跑,不过换一下参数,或者多跑几趟,就失败了。

#以下可以正常运行(当然,可能多跑几次,就失败)

./testusb -a -c10 -t1 -s4096 -g32 -v32

./testusb -a -c10 -t2 -s4096 -g32 -v32

./testusb -a -c10 -t3 -s4096 -g32 -v32

./testusb -a -c10 -t4 -s4096 -g32 -v512

./testusb -a -c10 -t5 -s512 -g32 -v512

./testusb -a -c10 -t6 -s512 -g32 -v512

./testusb -a -c10 -t7 -s512 -g32 -v512

./testusb -a -c10 -t8 -s512 -g32 -v512

./testusb -a -c10 -t9 -s512 -g32 -v256

./testusb -a -c10 -t10 -s512 -g16 -v32

./testusb -a -c10 -t11 -s512 -g32 -v256

./testusb -a -c10 -t12 -s512 -g32 -v256

./testusb -a -c10 -t13 -s512 -g32 -v256

./testusb -a -c10 -t14 -s256 -g32 -v1

#以下一般会出错

#./testusb -a -c10 -t4 -s4096 -g32 -v32 # error

#./testusb -a -c10 -t4 -s4096 -g32 -v256 # error

#./testusb -a -c10 -t7 -s512 -g32 -v32 #error

#./testusb -a -c10 -t7 -s512 -g32 -v256 #error

#./testusb -a -c10 -t8 -s512 -g32 -v32 #error

#./testusb -a -c10 -t8 -s512 -g32 -v256 #error

#./testusb -a -c10 -t10 -s512 -g32 -v256 #error

#./testusb -a -c10 -t14 -s512 -g32 -v256 #error

 

test.sh 脚本

在系统比较稳定后,可以使用 test.sh 进行耐力测试。 test.sh 的主要代码是一个没有退出条件的主循环,用户可以选择要测试的类型:

control: any device can do this

out, in:  out needs 'bulk sink' firmware, in needs 'bulk src'

iso-out, iso-in:  out needs 'iso sink' firmware, in needs 'iso src'

halt: needs bulk sink+src, tests halt set/clear from host

unlink: needs bulk sink and/or src, test HCD unlink processing

loop: needs firmware that will buffer N transfers

这样,我们就可以进行了各种单项测试。

比如: ./test.sh in | tee test_in.log

等等。

结论

根据要求,这些测试项应该运行 24 小时以上,由于目前某些基本测试就没有通过,还需要继续优化代码,再进行耐力测试。

参考

USB Testing on Linux

http://www.linux-usb.org/usbtest/index.html

 

你可能感兴趣的:(Embedded,Linux)