海思3531添加移遠EC20 4g模塊

在linux下加載驅動有兩種常用方法:靜態加載和動態加載。

  • 靜態加載就是把驅動程序直接編譯進內核,系統啓動後可以直接調用。靜態加載的缺點是調試起來比較麻煩,每次修改一個地方都要重新編譯和下載內核,效率較低。若採用靜態加載的驅動較多,會導致內核容量很大,浪費存儲空間。
  • 動態加載利用了Linux的module特性,可以在系統啓動後用insmod命令添加模塊(.ko),在不需要的時候用rmmod命令卸載模塊,採用這種動態加載的方式便於驅動程序的調試,同時可以針對產品的功能需求,進行內核的裁剪,將不需要的驅動去除,大大減小了內核的存儲容量。

在臺式機上,一般採用動態加載的方式;在嵌入式產品裏,可以先採用動態加載的方式進行調試,調試成功後再編譯進內核。

一開始在糾結是選擇模塊化添加驅動**.ko還是直接把驅動編譯進內核,既然我已經會燒寫內核了,那把驅動直接編譯進內核也不像想象中那麼困難,參照《UC20&EC20 Linux GobiNet User Guide》和網上一些資料,根據自己的理解,總結出海思3531添加移遠EC20模塊的詳細過程。

UC20是3g通信模塊,EC20是4g通信模塊;

1.   介紹

根據USB規範的規定,所有的USB設備都有供應商ID(VID)和產品識別碼(PID),主機通過不同的VID和PID來區別不同的設備,VID和PID都是兩個字節長,其中,供應商ID(VID)由供應商向USB執行論壇申請,每個供應商的VID是唯一的,PID由供應商自行決定(理論上來說,不同的產品、相同產品的不同型號、相同型號的不同設計的產品最好採用不同的PID,以便區別相同廠家的不同設備。)

VID和PID其實就相當於USB硬件的識別ID系統,也是通過他們來找到UC20/EC20設備的。

Product

PID

VID

UC20

0x9003

0x05c6

EC20

0x9215

0x05c6

2.   在Linux中集成GobiNet

爲了在Linux中爲Quectel模塊使用NDIS接口(Network Driver InterfaceSpecification,即網絡驅動接口規範),必須集成GobiNet驅動程序。在linux核中增加程序需要完成以下三項工作:

1.將編寫的源代碼添加到Linux內核源代碼的相應目錄

2.在目錄的Kconfig文件中增加新源代碼對應項目的編譯配置選項

3.在目錄的Makefile文件中增加對新源代碼的編譯條目

2.1    在內核中添加驅動源碼

  • 找到海思3531的內核源代碼版本並解壓它。
  • 將GobiNet驅動程序源代碼(ec20/DriveRSourceCode/src下的.c和.h文件)放入($_KERNELROOT)/ drivers / net / usb目錄中。($ _KERNELROOT)應該內核源代碼的根目錄。

2.2    解除USB串口驅動對NDIS接口的綁定

NDIS不是串口設備,因此要在串口驅動中去掉這個端口。在集成GobiNet驅動程序之前,先解除USB串口驅動對NDIS接口的綁定。

  • 打開源代碼根目錄中的文件:($_KERNELROOT)/drivers/usb/serial/option.c ,然後修改option_probe函數中的源代碼。注意到指導書給的修改示例和源代碼使用的變量名是不一樣的,把變量名也修改成一樣。

  • 網上還有增加PID&VID這一步(對這兩個不瞭解的,建議去找找資料來看看,這個的意思可以簡單理解爲這個設備的唯一標識),不過指導書裏沒有,還是加上了

代碼如下:

if (serial->dev->descriptor.idVendor== cpu_to_le16(0x05c6) &&
             serial->dev->descriptor.idProduct== cpu_to_le16(0x9215) &&
             serial->interface->cur_altsetting->desc.bInterfaceClass== 0x04)
             return-ENODEV;

2.3    將GobiNet添加到內核樹中

  • Kconfig文件定義了Linux內核配置菜單,config USB_GOBI_NET添加到($_KERNELROOT)/drivers/net/usb/Kconfig中。

代碼如下:

config USB_GOBI_NET

    tristate “Gobi USB Netdriver for Quectel module”

    help

    Support Quectel module.

 

    A modem manager withsupport for GobiNet is recommended.

    To compile this driver as amodule, choose M here: the module will be called GobiNet.
  • 修改($_KERNELROOT)/driver/net/usb/Makefile,在Makefile文件的末尾添加兩行代碼。

2.4    編譯內核並編譯驅動程序

在宿主機的Linux內核源碼根目錄執行以下指令,配置內核。添加GobiNet驅動:

host$ make ARCH=arm menuconfig

Kernel Configuration 界面,依次選擇:      

DeviceDrivers  --->

         Network device support  --->

                USB Network Adapters  --->

                     <*>Gobi USB Netdriver for Quectel module

如圖3-27所示:Save anAlternate Configuration File

按照賣家提供的內核依賴資料,選中Multi-purpose USB Networking Framework這一選項。

step.1        make menuconfig 出錯:

解決方案:換成 make ARCH=arm CROSS_COMPILE= arm-hisiv100-linux- menuconfig

step.2        make bzImage

makeARCH=arm CROSS_COMPILE= arm-hisi100-linux- bzImage

step.3        make modules

make ARCH=armCROSS_COMPILE=arm-hisiv100-linux- modules時出現各種錯誤

錯誤1   

drivers/ata/ahci_platform.c:251: error: 'CONFIG_HI_SATA_IOBASE' undeclared here (not in a function)
drivers/ata/ahci_platform.c:253: error: 'CONFIG_HI_SATA_IOSIZE' undeclared here (not in a function)
drivers/ata/ahci_platform.c:257: error: 'CONFIG_HI_SATA_IRQNUM' undeclared here (not in a function)
scripts/Makefile.build:311: recipe for target 'drivers/ata/ahci_platform.o' failed
make[2]: *** [drivers/ata/ahci_platform.o] Error 1
scripts/Makefile.build:441: recipe for target 'drivers/ata' failed
make[1]: *** [drivers/ata] Error 2
Makefile:945: recipe for target 'drivers' failed
make: *** [drivers] Error 2

解決方案

進入內核的drivers/ata/目錄,打開Makefile,看到“obj-$(CONFIG_SATA_AHCI_PLATFORM) +=ahci_platform.o libahci.o”;
打開drivers/ata/目錄下的Kconfig,搜索ATA_AHCI_PLATFORM,然後將這個下面的幾行代碼註釋掉;   
                    
在內核目錄下重新make menuconfig配置保存剛纔修改的內核(只需要進入menuconfig,然後保存退出)
之後再make內核,這樣能夠去掉之前出現的錯誤

錯誤2   

drivers/gpio/janz-ttl.c: In function 'ttl_set_value':
drivers/gpio/janz-ttl.c:107: error: implicit declaration of function 'iowrite16be'
scripts/Makefile.build:311: recipe for target 'drivers/gpio/janz-ttl.o' failed
make[2]: *** [drivers/gpio/janz-ttl.o] Error 1
scripts/Makefile.build:441: recipe for target 'drivers/gpio' failed
make[1]: *** [drivers/gpio] Error 2
Makefile:945: recipe for target 'drivers' failed
make: *** [drivers] Error 2

解決方案

在drivers/gpio/janz-ttl.c的前面加上下述定義
#define iowrite16be(v, addr) iowrite16(be16_to_cpu(v), (addr))

錯誤3

drivers/input/touchscreen/eeti_ts.c: In function 'eeti_ts_irq_active':
drivers/input/touchscreen/eeti_ts.c:65: error: implicit declaration of function 'irq_to_gpio'
scripts/Makefile.build:311: recipe for target 'drivers/input/touchscreen/eeti_ts.o' failed
make[3]: *** [drivers/input/touchscreen/eeti_ts.o] Error 1
scripts/Makefile.build:441: recipe for target 'drivers/input/touchscreen' failed
make[2]: *** [drivers/input/touchscreen] Error 2
scripts/Makefile.build:441: recipe for target 'drivers/input' failed
make[1]: *** [drivers/input] Error 2
Makefile:945: recipe for target 'drivers' failed
make: *** [drivers] Error 2

解決方案:更改的地方總共包括三個文件

  • arch/arm/mach-pxa/raumfeld.c
    
static struct eeti_ts_platform_data eeti_ts_pdata = {
.irq_active_high = 1,
.gpio = GPIO_TOUCH_IRQ,//添加
};
  • /drivers/input/touchscreen/eeti_ts.c
    
struct eeti_ts_priv
{
    struct input_dev *input;
    struct work_struct work;
    struct mutex mutex;
    int irq, irq_active_high;//刪除
    int irq, gpio, irq_active_high;//添加
};
static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv)
{
    return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high;//刪除
    return gpio_get_value(priv->gpio) == priv->irq_active_high;//添加
}


if (pdata)
    priv->irq_active_high = pdata->irq_active_high;
替換爲
if (pdata)
{
    priv->gpio = pdata->gpio;
    priv->irq_active_high = pdata->irq_active_high;
}
  • /include/linux/input/eeti_ts.
    
struct eeti_ts_platform_data 
{
    unsigned int irq_active_high;
    unsigned int gpio;//添加
};
到後面還是出現了各種錯誤,怎麼改也改不完,索性不編譯模塊了,
其實到STEP2已經編譯出內核了,不用step3也是可以的,step3出現的各種錯誤是在編譯各種我並不需要的模塊,直接燒寫剛剛得到的內核
0.設置地址
setenv serverip 192.168.1.50
1.燒寫內核
sf probe 0
mw.b 82000000 ff 400000
tftp 82000000 uImage
sf probe 0
sf erase 100000 400000
sf write 82000000 100000 400000

 

用hisiv100和hisiv200編譯出來的內核燒寫到板子上啓動時一直處於Starting kernel ...狀態,用100ntpl編譯的乾脆無法開機。網上說修改這個很麻煩,前面這些已經摺騰了一天了,看來燒寫內核是行不通了,再次放棄,選擇動態編譯GobiNet.ko 模塊試試。

驅動廠家給出的動態編譯流程:

編譯驅動源碼:注意修改你的內核路徑和交叉編譯器,編譯好後是GobiNet.ko,拷貝到板子上 insmod GobiNet.ko 就好
 編譯撥號聯網程序,注意修改makefile裏得交叉編譯器,編譯好後 quectel-CM,拷貝到板子上運行即可 ./quectel-CM&
然後ping www.baidu.com ping通證明就成功了

Linux Kernel 2.6要求你編譯模塊之前,必須先在內核源代碼目錄下執行make,換言之,你必須先配置過內核,執行過make,然後才能make你自己的模塊。(一開始指明的路徑是內核源代碼目錄,結果出現了許多錯誤),經過層層苦難終於出現了GobiNet.ko, insmod GobiNet.ko時出現了錯誤:

GobiNet: version magic '3.0.8 mod_unload ARMv5 ' should be '3.0.8 SMP mod_unload ARMv7 '
insmod: can't insert 'GobiNet.ko': invalid module format

出現這種問題一般是  開發板的內核版本號跟   要加載的編譯驅動模塊內核模塊版本號 不一致,內核文件與模塊兩者有很多東西必須匹配,編譯器版本、源碼版本、編譯時的配置等,所以當內核文件修改了,譬如修改了驅動的編譯選項(Y、M、N),那麼就必須重新編譯和下載內核,否則會出錯。

靜態加載無法開機,動態加載版本號不一致,網上也有一些解決版本號不一致問題的方法,嘗試多次無果。

這個過程也沒有走很多彎路,只是一開始接到這個任務的時候只是去網上找方法,沒有好好看廠家提供的資料。在改動的過程中,沒有注意到指導書給的修改示例和源代碼使用的變量名是不一樣的,一開始僅僅按照指導書裏說的去改,增加了自己的工作量。

補充:Makefile,Kconfig和配置工具組成了Linux2.6內核的配置系統。
     其中Makefile定義了Linux內核的編譯規則,它是大型項目開發的產物。Linux環境下的大型項目開發中,系統被分爲很多模塊,而這些模塊一般會經歷幾次修改,而在修改後的編譯過程中,由於某些文件中存在依賴關係,人工編譯效率低(有些文件不需要重新編譯)且易出錯,Makefile文件便應運而生。Makefile文件定義了模塊間的依賴關係,指定文件的編譯順序,以及編譯所使用的命令。它和make命令使得項目的源程序文件可以自動編譯,提高了軟件開發效率。到此,再談一下make,它是用來維護程序模塊關係和生成可執行程序的工具,它可以根據程序模塊的修改情況重新編譯鏈接生成中間代碼或最終的可執行程序,省去那些重複的不必要的編譯工作,提高編譯效率。
     Kconfig給用戶提供配置選擇的功能。通常配置內核會有四種方法,makeconfig(字符界面配置),makemenuconfig(菜單界面配置),makexconfig(依賴QT),makegconfig(依賴GTK+)。makeconfig比較適合專業人員,像初學者比較適合makemenuconfig,讓我們重點關注一下它。當我們運行makemenuconfig時,配置工具會首先分析與體系結構相對應的/arch/xxx/Kconfig文件(xxx爲傳入的arch參數),它裏面包含了除一些與體系結構相關的配置項和配置菜單外,還通過source語句引入了一系列Kconfig,配置工具依據這些Kconfig包含的菜單和項目就可以描繪出一個分層結構。
例如當我們運行makezImagine、makebzImagine等生成映像的命令時,會先檢索頂層的Makefile(在arch/xxx/目錄下的Makefile爲頂層Makefile補充體系結構相關的信息),頂層Makefile的兩個主要任務是:產生內核映像文件和內核模塊。接着頂層Makefile會去遞歸地進入內核的各個子目錄,然後分別調用子目錄中的Makefile(這些Makefile記錄編譯目標),而進入哪些子目錄取決於內核的配置。
        當使用makemenuconfig,makeconfig命令時,生成的.config會在源碼目錄下記錄哪些部分被編譯入內核,哪些部分被編譯爲內核模塊。簡而言之,它是保存內核配置結果的文件。當我們裝上Linux系統時,第一次查看源碼下的所有文件,會發現沒有.config文件,那是因爲從來沒配置過內核。當你運行makemenuconfig保存並退出時,再次查看就有這個文件了。
        配置工具,包括配置命令解釋器(對配置腳本中使用的命令進行解釋)和配置用戶界面(提供字符界面和圖形界面),配置工具都是用腳本語言編寫的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章