张 康
(桂林电子科技大学,广西 桂林 541004)
近年来,嵌入式系统越来越广泛应用于人们生活的方方面面。在很多的应用场景下,嵌入式设备需要与外界进行网络通信。传统的有线组网方案对设备的移动性和灵活性限制很大,越来越多的嵌入式设备需要采用无线网络进行数据传输。嵌入式ARM微处理器及技术的应用几乎已经深入到各个领域。而Linux操作系统作为一款免费、开源的操作系统,在保证可靠性、稳定性、多任务性、实时性的同时,又具有可裁减性和可定制性,并且对硬件设备具有丰富的支持,因而在嵌入式开发中得到了广泛的应用。基于以上,本文分析了Linux网络设备驱动结构,研究了基于ARM-Linux平台的无线网络设备搭建和配置方法。
相应的驱动例程,使控制从用户例程转移到驱动例程,完成相关操作后返回用户例程。
Linux的内核部分与设备驱动之间通过接口的形式进行标准化的互操作。对于每一类设备,如块设备、字符设备和网络设备都存在相应的通用接口以供硬件为内核提供相关服务。有了这些通用接口,内核就可以采用相同的方式来处理不同的硬件设备和它们的驱动程序。设备驱动程序是位于应用层和硬件设备之间的软件,它隐藏了设备的工作细节。它只负责处理硬件,而如何使用这些硬件设备则由应用程序来决定。应用程序对设备的使用是通过一系列标准形式的调用来完成的,而设备驱动程序负责将这些调用映射到对硬件设备特定的操作上。图 1描述了用户应用程序、系统内核、TCP/IP协议栈、网络设备驱动和硬件设备之间是如何进行交互的。
Linux设备驱动程序是Linux内核与硬件设备之间的软件接口。当内核需要对硬件设备进行操作的时候,它就调用
图1 Linux各层接口
在 Linux中,对于每一个网络设备,都用一个 struct device的数据结构作为内核空间和网络设备间的网络接口,网络驱动程序通过该接口进行网络数据传输。Linux网络驱动的体系结构可从上至下划分为以下四层,分别是网络协议接口层、网络设备接口层、设备驱动功能层、网络设备媒介层,如图2所示。
图2 Linux设备驱动结构
Linux 设备驱动,可以通过两种方式进行加载。一种是将设备驱动直接编译进系统内核,设备驱动将随着Linux内核的启动进行加载,内核启动完成之后,设备驱动功能也随即实现。这种方式会增加内核的大小,另外要在现有的内核中新增或删除功能,将不得不重新编译内核。第二种方式是通过模块进行加载。模块化设计使得Linux内核功能更容易扩展。这种方式可以控制内核大小, 并且方便对设备驱动的开发,每次修改驱动,只需重新编译驱动即可,无需再次编译内核,方便调试。本文中的网络设备驱动通过第二种方式进行加载:首先通过模块加载命令insmod将网络设备驱动程序加载到系统内核之中,之后insmod命令调用init_module函数对网络设备的 init函数指针进行初始化,并通过调用register_netdev()函数将该网络设备注册到系统中。接下来则调用 init函数指针指向的网络设备初始化函数对设备进行初始化,将设备的device数据结构插入到dev_base链表的末尾。如果要对模块进行卸载,可以通过执行命令 rmmod来调用网络驱动程序中的cleanup_module函数,对网络驱动程序模块进行卸载,具体过程如图3所示。
图3 Linux模块加载过程
本文中实现无线网络接入功能的目标平台为 Xilinx公司生产的ZC702开发板。该开发板的主芯片为Xilinx公司推出的Z-7020芯片。该芯片将FPGA(现场可编程逻缉器件)和双核ARM Cortex-A9 MPCore集成到一块器件中,将处理器的软件可编程能力与 FPGA 的硬件可编程能力实现无缝结合,具有突出的系统性能、灵活性、可扩展性。本设计采用无线网卡作为系统的无线接入设备,通过USB接口连接无线网卡与 ARM处理器。该系统中使用的无线网卡的主芯片是Ralink公司生产的RT3070,支持IEEE802.11n标准,传输速率最大支持150Mbps,支持操作系统Windows/Linux。
目标平台采用Linux操作系统,内核版本为3.0.0。宿主机使用的操作系统为 Windows系统,需要安装 VMware Workstation虚拟机,在虚拟机中安装运行Ubuntu10.0系统(内核板本为Linux 2.6.36)作为开发环境。交叉编译工具使用Xilinx提供的arm-xilinxa9-linux。
在虚拟机中启动 Ubuntu10.0,打开终端,进入Linux3.0.0内核目录/opt/linux-xlnx,在SHELL中运行命令make ARCH=arm menuconfig进入内核配置菜单,在菜单中配置内核选项,添加内核对Wlan的支持及对USB驱动的支持。
保存内核配置,进行内核编译:在SHELL中运行命令make ARCH=arm CROSS_COMPILE = arm-xilinxa9-linux-gnueabizImage。
编译结束后将在/opt/linux-xlnx/arch/arm/boot路径下生成zImage内核二进制文件,Linux3.0.0内核就编译好了。
4.2.1 修改Makefile文件
从Ralink官网获取RT3070的驱动程序源码。进入驱动源码目录/opt/rt3070,打开Makefile文件,进行修改,添加以下内容:
PLATFORM = Xarm
ifeq ($(PLATFORM),Xarm)
LINUX_SRC = /opt/linux-xlnx
CROSS_COMPILE = arm-xilinxa9-linux-gnueabi-
4.2.2 修改config.mk文件
进入目录/opt/rt3070/os/linux/,打开config.mk文件进行修改,修改内容如图4所示。
最后保存文件,开始交叉编译驱动,在SHELL中运行命令make ARCH=arm CROSS_COMPILE = arm-xilinxa9-linux-gnueabi-。最终生成rt3070sta.ko文件,交叉编译完成。
图4 config.mk文件修改内容
将目标板设置为SD卡启动方式,将编译好的内核映像文件及Uboot文件、设备树、根文件系统拷入SD卡中。启动开发板,进入操作系统,并通过串口终端在PC上进行显示。通过开发板的USB接口,使用U盘将相关文件拷贝到目标机中:
(1)把驱动源文件中的 RT2870STA.dat 拷贝到目标机根文件系统/etc/Wireless/RT2870STA/路径下。
(2)将驱动模块 rt3070sta.ko,拷贝到目标机根文件系统中,在SHELL中执行安装模块命令insmod rt3070sta.ko。
(3)从Ralink官网获取网卡固件rt2870.bin。将网卡固件拷贝到目标机根文件系统目录/lib/firmwire/下,在SHELL中执行命令 export FIRMWARE=/lib/firmware。再执行命令ifconfig ra0 up启动无线网卡。这样RT3070无线网卡就移植完毕了,此时网卡就可以开始工作了。
对无线网卡的设置需要使用无线网络配置工具,所以就要在目标板系统中安装相关配置工具。下面介绍使用wireless-tools工具的安装方法。
(1)可通过网络获取wireless-tools源码,修改其中的 Makefile文件。修改交叉编译工具路径为CROSS_COMPILE=/root/CodeSourcery/Sourcery_G++_Lite/b in/arm-xilinxa9-linux-gnueabi-。
(2)运行make命令,编译wireless-tools。
(3)拷贝生成的库文件libiw.so.29和libiw.so到目标板文件系统/lib目录下;拷贝iwconfig、iwlist、iwpriv等可执行文件到目标板文件系统/usr/bin目录下,wireless-tools工具就安装好了。
在完成网卡的移植及wireless-tools的安装后,就可对无线网卡进行配置和测试了。
(1)在目标平台上运行ifconfig ra0 up命令启用无线网卡。分别使用ifconfig ra0和iwconfig ra0可以查看无线网卡目前的状态。显示结果如图5所示。
图5 显示无线网卡状态
(2)要搜寻周围环境的无线网络信号可运行iwlist ra0 scanning命令,图6和图7中为搜寻到的部分无线网络,其中图7显示的是本次测试中使用无线路由器所产生的无线网络,其ESSID(扩展服务区标识)为“TEST”。
图6 部分无线网络信号
图7 测试用的无线路由信号
(3)运行命令iwconfig ra0 essid TEST,接入无线路由所在的测试网络。运行结果如图8所示。
图8 接入测试网络
(4)通过命令udhcpc –i ra0从无线路由获取动态分配的IP地址,运行结果如图9所示。
图9 动态获取IP地址
(5)无线路由的IP地址为192.168.1.1。在目标平台上运行ping 192.168.1.1,有数据返回,表明目标平台的无线网卡和无线路由间的网络是连通的。该无线网络中另一台主机的IP地址为192.168.1.100,再次运行ping命令进行测试,结果显示无线网卡和该主机的网络是连通的。Ping命令的显示结果如图10所示。
图10 Ping命令运行结果
本文对Linux网络设备驱动的体系结构和工作原理进行了分析,研究了ARM-Linux平台接入无线网络的实现方案,将无线网卡移植到目标平台,并进行了相关配置及测试。结果表明,该方案成功实现了嵌入式系统的无线接入功能,使用嵌入式设备的数据传输方式更加灵活。
[1] Gene Sally. Linux嵌入式系统高级程序设计[M].郭旭,译.北京:人民邮电出版社,2010.
[2] 商斌.嵌入式Linux C语言开发入门与编程实践[M].北京:电子工业出版社,2008.
[3] 赵炯.Linux内核完全注释[M].北京:机械工业出版社,2004.
[4] 郭磊,廖启征,魏世民.基于ARM9系统的USB无线网卡驱动程序设计[J].计算机系统应用,2007(1):92-94.
[5] 杨宗德.嵌入式 ARM 系统原理与实例开发[M].北京:北京大学出版社,2010.