張 康
(桂林電子科技大學(xué),廣西 桂林 541004)
近年來,嵌入式系統(tǒng)越來越廣泛應(yīng)用于人們生活的方方面面。在很多的應(yīng)用場景下,嵌入式設(shè)備需要與外界進(jìn)行網(wǎng)絡(luò)通信。傳統(tǒng)的有線組網(wǎng)方案對設(shè)備的移動性和靈活性限制很大,越來越多的嵌入式設(shè)備需要采用無線網(wǎng)絡(luò)進(jìn)行數(shù)據(jù)傳輸。嵌入式ARM微處理器及技術(shù)的應(yīng)用幾乎已經(jīng)深入到各個領(lǐng)域。而Linux操作系統(tǒng)作為一款免費(fèi)、開源的操作系統(tǒng),在保證可靠性、穩(wěn)定性、多任務(wù)性、實(shí)時性的同時,又具有可裁減性和可定制性,并且對硬件設(shè)備具有豐富的支持,因而在嵌入式開發(fā)中得到了廣泛的應(yīng)用。基于以上,本文分析了Linux網(wǎng)絡(luò)設(shè)備驅(qū)動結(jié)構(gòu),研究了基于ARM-Linux平臺的無線網(wǎng)絡(luò)設(shè)備搭建和配置方法。
相應(yīng)的驅(qū)動例程,使控制從用戶例程轉(zhuǎn)移到驅(qū)動例程,完成相關(guān)操作后返回用戶例程。
Linux的內(nèi)核部分與設(shè)備驅(qū)動之間通過接口的形式進(jìn)行標(biāo)準(zhǔn)化的互操作。對于每一類設(shè)備,如塊設(shè)備、字符設(shè)備和網(wǎng)絡(luò)設(shè)備都存在相應(yīng)的通用接口以供硬件為內(nèi)核提供相關(guān)服務(wù)。有了這些通用接口,內(nèi)核就可以采用相同的方式來處理不同的硬件設(shè)備和它們的驅(qū)動程序。設(shè)備驅(qū)動程序是位于應(yīng)用層和硬件設(shè)備之間的軟件,它隱藏了設(shè)備的工作細(xì)節(jié)。它只負(fù)責(zé)處理硬件,而如何使用這些硬件設(shè)備則由應(yīng)用程序來決定。應(yīng)用程序?qū)υO(shè)備的使用是通過一系列標(biāo)準(zhǔn)形式的調(diào)用來完成的,而設(shè)備驅(qū)動程序負(fù)責(zé)將這些調(diào)用映射到對硬件設(shè)備特定的操作上。圖 1描述了用戶應(yīng)用程序、系統(tǒng)內(nèi)核、TCP/IP協(xié)議棧、網(wǎng)絡(luò)設(shè)備驅(qū)動和硬件設(shè)備之間是如何進(jìn)行交互的。
Linux設(shè)備驅(qū)動程序是Linux內(nèi)核與硬件設(shè)備之間的軟件接口。當(dāng)內(nèi)核需要對硬件設(shè)備進(jìn)行操作的時候,它就調(diào)用

圖1 Linux各層接口
在 Linux中,對于每一個網(wǎng)絡(luò)設(shè)備,都用一個 struct device的數(shù)據(jù)結(jié)構(gòu)作為內(nèi)核空間和網(wǎng)絡(luò)設(shè)備間的網(wǎng)絡(luò)接口,網(wǎng)絡(luò)驅(qū)動程序通過該接口進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳輸。Linux網(wǎng)絡(luò)驅(qū)動的體系結(jié)構(gòu)可從上至下劃分為以下四層,分別是網(wǎng)絡(luò)協(xié)議接口層、網(wǎng)絡(luò)設(shè)備接口層、設(shè)備驅(qū)動功能層、網(wǎng)絡(luò)設(shè)備媒介層,如圖2所示。

圖2 Linux設(shè)備驅(qū)動結(jié)構(gòu)
Linux 設(shè)備驅(qū)動,可以通過兩種方式進(jìn)行加載。一種是將設(shè)備驅(qū)動直接編譯進(jìn)系統(tǒng)內(nèi)核,設(shè)備驅(qū)動將隨著Linux內(nèi)核的啟動進(jìn)行加載,內(nèi)核啟動完成之后,設(shè)備驅(qū)動功能也隨即實(shí)現(xiàn)。這種方式會增加內(nèi)核的大小,另外要在現(xiàn)有的內(nèi)核中新增或刪除功能,將不得不重新編譯內(nèi)核。第二種方式是通過模塊進(jìn)行加載。模塊化設(shè)計(jì)使得Linux內(nèi)核功能更容易擴(kuò)展。這種方式可以控制內(nèi)核大小, 并且方便對設(shè)備驅(qū)動的開發(fā),每次修改驅(qū)動,只需重新編譯驅(qū)動即可,無需再次編譯內(nèi)核,方便調(diào)試。本文中的網(wǎng)絡(luò)設(shè)備驅(qū)動通過第二種方式進(jìn)行加載:首先通過模塊加載命令insmod將網(wǎng)絡(luò)設(shè)備驅(qū)動程序加載到系統(tǒng)內(nèi)核之中,之后insmod命令調(diào)用init_module函數(shù)對網(wǎng)絡(luò)設(shè)備的 init函數(shù)指針進(jìn)行初始化,并通過調(diào)用register_netdev()函數(shù)將該網(wǎng)絡(luò)設(shè)備注冊到系統(tǒng)中。接下來則調(diào)用 init函數(shù)指針指向的網(wǎng)絡(luò)設(shè)備初始化函數(shù)對設(shè)備進(jìn)行初始化,將設(shè)備的device數(shù)據(jù)結(jié)構(gòu)插入到dev_base鏈表的末尾。如果要對模塊進(jìn)行卸載,可以通過執(zhí)行命令 rmmod來調(diào)用網(wǎng)絡(luò)驅(qū)動程序中的cleanup_module函數(shù),對網(wǎng)絡(luò)驅(qū)動程序模塊進(jìn)行卸載,具體過程如圖3所示。

圖3 Linux模塊加載過程
本文中實(shí)現(xiàn)無線網(wǎng)絡(luò)接入功能的目標(biāo)平臺為 Xilinx公司生產(chǎn)的ZC702開發(fā)板。該開發(fā)板的主芯片為Xilinx公司推出的Z-7020芯片。該芯片將FPGA(現(xiàn)場可編程邏緝器件)和雙核ARM Cortex-A9 MPCore集成到一塊器件中,將處理器的軟件可編程能力與 FPGA 的硬件可編程能力實(shí)現(xiàn)無縫結(jié)合,具有突出的系統(tǒng)性能、靈活性、可擴(kuò)展性。本設(shè)計(jì)采用無線網(wǎng)卡作為系統(tǒng)的無線接入設(shè)備,通過USB接口連接無線網(wǎng)卡與 ARM處理器。該系統(tǒng)中使用的無線網(wǎng)卡的主芯片是Ralink公司生產(chǎn)的RT3070,支持IEEE802.11n標(biāo)準(zhǔn),傳輸速率最大支持150Mbps,支持操作系統(tǒng)Windows/Linux。
目標(biāo)平臺采用Linux操作系統(tǒng),內(nèi)核版本為3.0.0。宿主機(jī)使用的操作系統(tǒng)為 Windows系統(tǒng),需要安裝 VMware Workstation虛擬機(jī),在虛擬機(jī)中安裝運(yùn)行Ubuntu10.0系統(tǒng)(內(nèi)核板本為Linux 2.6.36)作為開發(fā)環(huán)境。交叉編譯工具使用Xilinx提供的arm-xilinxa9-linux。
在虛擬機(jī)中啟動 Ubuntu10.0,打開終端,進(jìn)入Linux3.0.0內(nèi)核目錄/opt/linux-xlnx,在SHELL中運(yùn)行命令make ARCH=arm menuconfig進(jìn)入內(nèi)核配置菜單,在菜單中配置內(nèi)核選項(xiàng),添加內(nèi)核對Wlan的支持及對USB驅(qū)動的支持。
保存內(nèi)核配置,進(jìn)行內(nèi)核編譯:在SHELL中運(yùn)行命令make ARCH=arm CROSS_COMPILE = arm-xilinxa9-linux-gnueabizImage。
編譯結(jié)束后將在/opt/linux-xlnx/arch/arm/boot路徑下生成zImage內(nèi)核二進(jìn)制文件,Linux3.0.0內(nèi)核就編譯好了。
4.2.1 修改Makefile文件
從Ralink官網(wǎng)獲取RT3070的驅(qū)動程序源碼。進(jìn)入驅(qū)動源碼目錄/opt/rt3070,打開Makefile文件,進(jìn)行修改,添加以下內(nèi)容:
PLATFORM = Xarm
ifeq ($(PLATFORM),Xarm)
LINUX_SRC = /opt/linux-xlnx
CROSS_COMPILE = arm-xilinxa9-linux-gnueabi-
4.2.2 修改config.mk文件
進(jìn)入目錄/opt/rt3070/os/linux/,打開config.mk文件進(jìn)行修改,修改內(nèi)容如圖4所示。
最后保存文件,開始交叉編譯驅(qū)動,在SHELL中運(yùn)行命令make ARCH=arm CROSS_COMPILE = arm-xilinxa9-linux-gnueabi-。最終生成rt3070sta.ko文件,交叉編譯完成。

圖4 config.mk文件修改內(nèi)容
將目標(biāo)板設(shè)置為SD卡啟動方式,將編譯好的內(nèi)核映像文件及Uboot文件、設(shè)備樹、根文件系統(tǒng)拷入SD卡中。啟動開發(fā)板,進(jìn)入操作系統(tǒng),并通過串口終端在PC上進(jìn)行顯示。通過開發(fā)板的USB接口,使用U盤將相關(guān)文件拷貝到目標(biāo)機(jī)中:
(1)把驅(qū)動源文件中的 RT2870STA.dat 拷貝到目標(biāo)機(jī)根文件系統(tǒng)/etc/Wireless/RT2870STA/路徑下。
(2)將驅(qū)動模塊 rt3070sta.ko,拷貝到目標(biāo)機(jī)根文件系統(tǒng)中,在SHELL中執(zhí)行安裝模塊命令insmod rt3070sta.ko。
(3)從Ralink官網(wǎng)獲取網(wǎng)卡固件rt2870.bin。將網(wǎng)卡固件拷貝到目標(biāo)機(jī)根文件系統(tǒng)目錄/lib/firmwire/下,在SHELL中執(zhí)行命令 export FIRMWARE=/lib/firmware。再執(zhí)行命令ifconfig ra0 up啟動無線網(wǎng)卡。這樣RT3070無線網(wǎng)卡就移植完畢了,此時網(wǎng)卡就可以開始工作了。
對無線網(wǎng)卡的設(shè)置需要使用無線網(wǎng)絡(luò)配置工具,所以就要在目標(biāo)板系統(tǒng)中安裝相關(guān)配置工具。下面介紹使用wireless-tools工具的安裝方法。
(1)可通過網(wǎng)絡(luò)獲取wireless-tools源碼,修改其中的 Makefile文件。修改交叉編譯工具路徑為CROSS_COMPILE=/root/CodeSourcery/Sourcery_G++_Lite/b in/arm-xilinxa9-linux-gnueabi-。
(2)運(yùn)行make命令,編譯wireless-tools。
(3)拷貝生成的庫文件libiw.so.29和libiw.so到目標(biāo)板文件系統(tǒng)/lib目錄下;拷貝iwconfig、iwlist、iwpriv等可執(zhí)行文件到目標(biāo)板文件系統(tǒng)/usr/bin目錄下,wireless-tools工具就安裝好了。
在完成網(wǎng)卡的移植及wireless-tools的安裝后,就可對無線網(wǎng)卡進(jìn)行配置和測試了。
(1)在目標(biāo)平臺上運(yùn)行ifconfig ra0 up命令啟用無線網(wǎng)卡。分別使用ifconfig ra0和iwconfig ra0可以查看無線網(wǎng)卡目前的狀態(tài)。顯示結(jié)果如圖5所示。

圖5 顯示無線網(wǎng)卡狀態(tài)
(2)要搜尋周圍環(huán)境的無線網(wǎng)絡(luò)信號可運(yùn)行iwlist ra0 scanning命令,圖6和圖7中為搜尋到的部分無線網(wǎng)絡(luò),其中圖7顯示的是本次測試中使用無線路由器所產(chǎn)生的無線網(wǎng)絡(luò),其ESSID(擴(kuò)展服務(wù)區(qū)標(biāo)識)為“TEST”。

圖6 部分無線網(wǎng)絡(luò)信號

圖7 測試用的無線路由信號
(3)運(yùn)行命令iwconfig ra0 essid TEST,接入無線路由所在的測試網(wǎng)絡(luò)。運(yùn)行結(jié)果如圖8所示。

圖8 接入測試網(wǎng)絡(luò)
(4)通過命令udhcpc –i ra0從無線路由獲取動態(tài)分配的IP地址,運(yùn)行結(jié)果如圖9所示。

圖9 動態(tài)獲取IP地址
(5)無線路由的IP地址為192.168.1.1。在目標(biāo)平臺上運(yùn)行ping 192.168.1.1,有數(shù)據(jù)返回,表明目標(biāo)平臺的無線網(wǎng)卡和無線路由間的網(wǎng)絡(luò)是連通的。該無線網(wǎng)絡(luò)中另一臺主機(jī)的IP地址為192.168.1.100,再次運(yùn)行ping命令進(jìn)行測試,結(jié)果顯示無線網(wǎng)卡和該主機(jī)的網(wǎng)絡(luò)是連通的。Ping命令的顯示結(jié)果如圖10所示。

圖10 Ping命令運(yùn)行結(jié)果
本文對Linux網(wǎng)絡(luò)設(shè)備驅(qū)動的體系結(jié)構(gòu)和工作原理進(jìn)行了分析,研究了ARM-Linux平臺接入無線網(wǎng)絡(luò)的實(shí)現(xiàn)方案,將無線網(wǎng)卡移植到目標(biāo)平臺,并進(jìn)行了相關(guān)配置及測試。結(jié)果表明,該方案成功實(shí)現(xiàn)了嵌入式系統(tǒng)的無線接入功能,使用嵌入式設(shè)備的數(shù)據(jù)傳輸方式更加靈活。
[1] Gene Sally. Linux嵌入式系統(tǒng)高級程序設(shè)計(jì)[M].郭旭,譯.北京:人民郵電出版社,2010.
[2] 商斌.嵌入式Linux C語言開發(fā)入門與編程實(shí)踐[M].北京:電子工業(yè)出版社,2008.
[3] 趙炯.Linux內(nèi)核完全注釋[M].北京:機(jī)械工業(yè)出版社,2004.
[4] 郭磊,廖啟征,魏世民.基于ARM9系統(tǒng)的USB無線網(wǎng)卡驅(qū)動程序設(shè)計(jì)[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2007(1):92-94.
[5] 楊宗德.嵌入式 ARM 系統(tǒng)原理與實(shí)例開發(fā)[M].北京:北京大學(xué)出版社,2010.