1. 程式人生 > >Linux開發板中安裝WIFI驅動

Linux開發板中安裝WIFI驅動

嵌入式開發板用的是Cubieboard2,linux版本3.4.60+(linux-sunxi3.4),檔案系統是debian。WIFI用的是水星USB網絡卡,型號MW150US。
1.Cubieboard2支援的驅動
   首先查了一下Cubieboard2自身支援的wifi驅動,官方系統自帶rtl8192cu和bcm4330的驅動,所以只要只這兩個晶片的wifi都可以用直接用。其他的需要編譯驅動,如 rtl8188,rtl8187 經測編譯驅動後可用。
2.網絡卡的晶片型號
   網絡卡沒有附帶驅動,也沒說明書,好在包裝盒上寫了型號,百度了一下,它採用的晶片是rtl8188eu,ID是8179(一開始看到有的說這個網絡卡採用的晶片是8188,有的說晶片是8179,關於這個疑惑了半天,後來下面連結中的文章才知道原來8179是ID,代表的就是rtl8188eu晶片。
   把網絡卡插到裝置上,使用#lsusb命令檢視系統中的USB裝置,結果如下:
#Bus 001 Device 003: ID 0bda:8179 RealtekSemiconductor Corp. 
3.下載和編譯驅動
   確定了網絡卡晶片之後就找rtl8188eu晶片的驅動了,從下面這個連結中下載了一個,解壓之後開啟Makefile。做如下修改:
1 把Cubieboard2對應的平臺後面改為”y”。 CONFIG_PLATFORM_ARM_SUN4I = y
2 再到此平臺對應的變數區域修改一下核心路徑。
KSRC:=/opt/Cubieboard/linux-sunxi
   然後make。但是編譯進行了幾分鐘之後出現了錯誤,提示:
os_dep/osdep_service.c:1283:21:error:'struct wake_lock' has no member named 'link'
   查看了osdep_service.c原始碼,其中沒有定義struct wake_lock這個結構體,而它包含的標頭檔案也都是< XXX.h>,沒有”XXX.h”的,所以這個結構體定義引起的錯誤不是這個驅動的原始檔造成的,應該是它的#include中用到的標頭檔案造成的。所以這應該是linux核心版本造成的,或者說我所用的這個驅動和linux版本是不匹配的。
   我又試了一下PC上(在虛擬機器中安裝的系統是Ubuntu12.04)安裝此驅動,把平臺修改一下:CONFIG_PLATFORM_I386_PC= y,又出現一堆錯誤,再看一下連結中的說明,只支援linux3.9以下的版本,我的核心版本是3.11,不過在/lib/modules/下還有一個3.2版本的資料夾(只不過裡面只有一個build資料夾)。然後在Makefile的PC平臺變數對應的位置修改成這個3.2版本。再次make就通過了,生成了8818eu.ko檔案。只不過insmod的時候就出錯了(肯定會出錯啊,編譯得到的驅動版本和正在執行的核心版本不一致嘛,我只不過是想驗證下樓主說的支援3.9版本以下的核心)
   所以問題又回到“上哪裡去找驅動”。又讓我找到個,見下面的連結,原來我以前下載的linux-sunxi的drivers/net/wireless下本身就有rtl8818eu的原始碼,只不過在menuconfig配置核心的時候,這個不會出現在圖形介面上,需要把這整個資料夾拷貝出來,手動編譯下。
   編譯之前先修改rtl8188eu的Makefile,在檔案最開頭新增:CONFIG_RTL8188EU=m。另外還是照例修改下平臺,和平臺對應的變數。
CONFIG_RTL8188EU=m
……
CONFIG_PLATFORM_ARM_SUN4I= y
……
ifeq($(CONFIG_PLATFORM_ARM_SUN4I), y)
KSRC:=/opt/Cubieboard/linux-sunxi
CROSS_COMPILE := arm-linux-gnueabihf-gcc
KVER  := 3.4
……
endif
再次make,這回沒有錯誤生成了8818eu.ko。
4.安裝驅動
   將剛剛得到的8818eu.ko拷貝到開發板上,#insmod 8818eu.ko,出現以下錯誤:
#ERR: script_parser_fetch usb_wifi_usbc_numfailed
#ERR: script_parser_fetch usb_wifi_usbc_numfailed
#Error: could not insert module 8188eu.ko:Cannot allocate memory
   這裡的usb_wifi_usbc_num表示usbc對應的realtekusb無線晶片的序號。這是因為在script.bin檔案(script.bin是被全志SOC核心驅動或LiveSuit使用的針對特定目標板的二進位制配置檔案,包含如何設定基於A10/A20目標版的各種外設,埠,I/O針腳資訊)中缺少了 usb_wifi_para 引數的設定,這時候必須修改script.bin檔案,在其中新增以下內容:
[usb_wifi_para]
usb_wifi_used= 1
usb_wifi_usbc_num= 2
   但是script.bin是通過script.fex來生成的,不能直接用文字文件開啟script.bin,需要先修改script.fex,用fex2bin工具轉換成script.bin。
#cd/opt/Cubieboard/rootfs
#/opt/Cubieboard /sunxi-tools/fex2bin boot/script.fex boot/script.bin
   替換掉開發板中原來的script.bin即可。
   再次#insmod 8818eu.ko,出現以下提示,這回終於成功了。
#usbcore: registered new interface driverrtl8188eu
5.後續遇到的問題
   之後把整套系統裝配起來,USB攝像頭和WIFI一起使用,(攝像頭以前使用過,一切正常),發生如下錯誤:
#insmod 8188eu.ko 
8188eu: disagrees about version of symbol module_layout
Error: could not insert module 8188eu.ko: Invalid module format
   猜想可能是核心亂了需要重新編譯下吧,反覆配置了幾次,到最後,連WIFI單獨使用也不行了。上面的這個錯誤貌似挺偏門,遇到的人不多,後來查到這篇解釋這個是什麼錯誤的。
1.編譯kernel的時候,會生成Module.symvers檔案,記錄每個Symbol 和相應的CRC code,例如:
0x258d700e raw_seq_open vmlinux EXPORT_SYMBOL_GPL
0xebba1d26 device_add vmlinux EXPORT_SYMBOL_GPL
0xfb0f0e78 device_del vmlinux EXPORT_SYMBOL_GPL
2.編寫動態載入module的時候,也會生成類似的檔案module_name.mod.c,將module呼叫到的system call 記錄在裡面,這個的symbol使用編譯module的時候指向的kernel路徑。比如這個kernel 版本是2.6.37-2.5。
3.載入這個動態module的時候,kernel會去check載入模組的每一個symbol的CRC,看看是否與kernel相應的symbol相同,不同的話就會報錯。同一個kernel版本,不同的config也會出這個問題。
  我查看了這兩個檔案,關於module_layout的CRC值果然不一樣。那麼應該還是核心配置的問題。不過CRC的值的檢查問題貌似也不是大問題(看到一些博主說這個主要是用來檢測版本的,但是細微的版本區別也造成這個值不匹配,可以關掉這個檢測),硬是要用的話,驅動還是可以用的,雖然它提示could not insert module 8188eu.ko,但實際上我#lsmod可以看到驅動已經成功載入的。並且我用一個編寫的檔案傳輸的小程式來測試,發現傳輸可以正常進行。
又配了幾次核心,編譯了幾次8818eu驅動,module_layout的CRC值還是不一樣,後來不知怎的,連8818eu的編譯也通不過了(我只修改了Makefile呀)。
   後來很偶然的,我把WIFI插著的時候上電,啟動資訊中竟然列印驅動載入成功了:
usbcore: registered new interface driver rtl8188eu
   可這時候我還沒有insmod呢。我又插拔了幾次WIFI模組,都能夠成功裝載。這自動裝載的現象,是在編譯的時候就直接選擇了模組編譯的方式,然後安裝到指定路徑下的驅動才有的表現,可是我make menuconfig中根本沒看到這個選項,所以我才把驅動拷貝到/opt下手動insmod的。我到系統的驅動檔案路徑下去找,果然找到了8188eu.ko。
   這下迷題解開了,第一,首先上面的錯誤提示的確是核心配置和驅動編譯造成的,我中間反覆配置過幾次,但是並不是每次都重新從driver下拷貝檔案重新編譯。第二,我首次安裝驅動時沒有遇到這個錯誤,那時的核心配置中我沒有把這個驅動選上,開發板的驅動檔案路徑下沒有8188eu.ko檔案。
6. 將驅動直接編譯進核心
  把整個驅動的原始檔包放到你選定的路徑下,例如drivers/net/wireless,找到路徑下的Kconfig,在裡面新增一行:source "drivers/net/wireless/rtl8188eu/Kconfig"
  那麼你使用make menuconfig 時就能看到對應項了,要是你不知道哪個項才是自己的驅動,就開啟原始檔包的的Kconfig檢視下。