PL2303在ARM Linux下驱动的问题及解决方法

问题描述:项目需要用ARM板驱动金笛wavecom GSM模块发短信,该GSM模块为USB接口,内部采用PL2303HX芯片转为RS232接口实现AT指令协议。

将GSM模块插入ARM板的USB口,发现没有驱动。

进一步解决步骤:将GSM模块插入PC机的USB口,在Ubuntu 10.04下可以正确的识别为/dev/ttyUSB0。用minicom测试,功能正常。

由于没有ARM Linux驱动,尝试寻找ARM Linux 的内核驱动模块。上网查找资料,PL2303芯片驱动应该已经集成到了Linux的内核源码中,只是ARM Linux 把它剪裁掉了,需要重新编译为内核模块,并加载。

我的ARM环境为AT91SAM9261 CPU,Linux 版本为2.6.27,开发机为ubuntu 10.04。

去ATmel官方网站下载Linux内核源代码:

http://www.at91.com/linux4sam/bin/view/Linux4SAM/LinuxKernel

找到VANILLA Linux Kernel 的源代码包链接并下载: http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.27.tar.bz2 ,解压到home下。在主文件夹中多了一个linux-2.6.27文件夹。

一并下载9261的内核配置文件ftp://www.at91.com/pub/linux/2.6.27-at91/at91sam9261ek_defconfig,下载到linux-2.6.27下,并且命名为.config

cd linux-2.6.27
make ARCH=arm menuconfig

在Device Drivers->USB Support --->USB Serial Converter Support选项,默认是没选中的。在该项中按M键,回车,就可以进入到下级菜单,找到USB Prolific 2303 Single Port Serial Driver项,按M选中,将本级的其它选项的M清空。M的意思是按模块编译,*是编译集成进内核。我们不需要编译整个内核。

设置好之后,保存退出。

在执行以下命令:

make ARCH=arm CROSS_COMPILE=/usr/local/arm/arm-2008q1/bin/arm-linux- modules

我的交叉编译toolchain的路径是/usr/local/arm/arm-2008q1/,这里要修改成你自己的路径。

编译完成后,在drivers/usb/serial下,生成了pl2303.ko文件。将该文件下载到ARM板上,在ARM命令行执行

insmod pl2303.ko
可以通过dmesg查看驱动模块加载情况:

# dmesg
usbserial: USB Serial support registered for pl2303
usbcore: registered new interface driver pl2303
pl2303: Prolific PL2303 USB to serial adaptor driver
说明驱动已经成功加载,插入GSM模块,会在/dev下出现ttyUSB0设备。

如果在这里出现invalid module format的错误,是因为在 make menuconfig的时候,没有正确配置CPU型号。下载对应的defconfig文件(本文对应的是at91sam9261ek_defconfig)即可解决问题。

至此,驱动安装成功。


在ARM上调试串口,我使用了一个简化版的类似minicom的源代码。下载地址:http://plunk.org/~grantham/serial.cpp


但是,进一步发现,通过ARM上的ttyUSB0与GSM模块无法通讯,表现为数据发不过去,也收不到任何应答。为了确定问题,用另一个PL2303的USB转RS232的转接头接在ARM板上,另一端通过串口数据线连接到PC上,在PC上用串口调试助手调试,居然可以正常的收发数据。

GSM连PC,正常,说明GSM模块没问题,ARM连PC,也正常,说明ARM和驱动也没问题,唯独GSM连ARM不正常。怪哉!于是将GSM模块拆开,用示波器测量PL2303芯片的RS232输出引脚电平,当GSM连PC时,输出电平波形正常,当GSM连ARM时,没有输出电平。也就是说,2303芯片根本就没有向GSM模块输出信号。当然也不会有任何回应。

问题指向了pl2303的linux驱动。

打开drivers/usb/serial/pl2303.c文件,发现以下一段代码:

enum pl2303_type {
        type_0,         /* don't know the difference between type 0 and */
        type_1,         /* type 1, until someone from prolific tells us... */
        HX,             /* HX version of the pl2303 chip */
};

也就是说驱动里可以识别pl2303芯片有三种类型type_0, type_1和HX。而驱动的作者也不知道几个类型之间有什么区别。

再次在ARM板上,以调试模式加载驱动模块:

insmod pl2303.ko debug=1

dmesg

发现识别为device type = 1,但是在芯片的标签上,明确标明型号为“PL2303HX”。就是说驱动程序把芯片的型号识别错了。

经过仔细阅读代码和反复调试,最终将以下代码

if (serial->dev->descriptor.bDeviceClass == 0x02)
                type = type_0;
        else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
                type = HX;
        else if (serial->dev->descriptor.bDeviceClass == 0x00)
                type = type_1;
        else if (serial->dev->descriptor.bDeviceClass == 0xFF)
                type = type_1;

修改为

if (serial->dev->descriptor.bDeviceClass == 0x02)
                type = type_0;
        else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
                type = HX;
        else if (serial->dev->descriptor.bMaxPacketSize0 == 0x02)
                type = HX;
        else if (serial->dev->descriptor.bDeviceClass == 0x00)
                type = type_1;
        else if (serial->dev->descriptor.bDeviceClass == 0xFF)
                type = type_1;

重新编译pl2303驱动,至此,问题全部解决。


你可能感兴趣的:(PL2303在ARM Linux下驱动的问题及解决方法)