天天看點

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驅動,至此,問題全部解決。

繼續閱讀