Linux移植RT73驱动

        首先,到http://www.ralinktech.com/cn/04_support/support.php?sn=501 上去下载最新的RT73驱动(RT73的一个别称是RT2501USB),我刚开始的时候在别的地方下载的2009_0206_RT73_Linux_STA_Drv1.1.0.2.tar.bz2 这个驱动在linux-2.6.31(ubuntu10.10)内核上编译时不能通过,看了网上的一些移植步骤他们基本上是在linux-2.6.22内核下移植的,由于linux-2.6.31内核肯能在数据结构上做了修改,所以在对该驱动make的时候会提示缺少某些参数(后来再次编译的时候却通过了,忘了在哪里做了修改了)。

        1、如果是用在ubuntu上用ubuntu的gcc而不用交叉编译器XX-gcc则可以不做修改直接在其Module目录下make便可以直接生成能够在ubuntu上使用的RT73.ko驱动文件;

        2、如果目标系统是ARM则需要使用交叉编译器,仅需对Module下的Makefile做一些修改便可以了,修改内容如下(这里是参考http://linux.chinaunix.net/techdoc/install/2009/03/26/1105858.shtml):

(1)CC     :=arn-linux-gcc
(2)LD     :=arm-linux-ld
#PLATFORM=PC
(3)PLATFORM=CMPC

#Enable for wpa_supplicant's spcific driver "driver_ralink.c", default enabled.
HAS_RALINK_WPA_SUPPLICANT_SUPPORT=y
#Enable for wpa_supplicant's generic driver "driver_wext.c", used for NetworkManager
HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=n
#Support Block Net-If during TxSw queue full.
HAS_BLOCK_NET_IF=y
WFLAGS := -Wall -Wstrict-prototypes -Wno-trigraphs
ifeq ($(HAS_RALINK_WPA_SUPPLICANT_SUPPORT),y)
WFLAGS += -DRALINK_WPA_SUPPLICANT_SUPPORT
endif
ifeq ($(HAS_NATIVE_WPA_SUPPLICANT_SUPPORT),y)
WFLAGS += -DNATIVE_WPA_SUPPLICANT_SUPPORT
endif
ifeq ($(HAS_BLOCK_NET_IF),y)
WFLAGS += -DBLOCK_NET_IF
endif
## Comment/uncomment the following line to enable/disable debugging
#EXTRA_CFLAGS += -DDBG
EXTRA_CFLAGS += $(WFLAGS)
ifeq ($(PLATFORM),PC)
LINUX_SRC =/lib/modules/$(shell uname -r)/build
endif
ifeq ($(PLATFORM),CMPC)
#LINUX_SRC = /home/fonchi/vendor/kernel-default-2.6.21/linux-2.6.21
(4)LINUX_SRC =/home/chen/Hi3515_SDK_V1.0.2.0.c1/source/os/linux-2.6.24

endif 

........

(5)make -C $(LINUX_SRC) SUBDIRS=$(shell pwd) modules

........

        这里修改的内容是指定交叉编译器和Linux内核源码的路径,(1)处指定了交叉编译器;(2)处指定了链接器;(其实我觉得这两个步骤是没有必要的,因为在这个驱动的makefile里没有使用到CC和ARCH,打开驱动的makefile可以看到我们在make的时候实际上执行的是makefile里的(5)处这一行代码,然后直接到内核的makefile中执行,这时用的就是内核的makefile指定的CC编译器,反正在我的内核下的makefile是这样的)3)是一个选项,用于在ifeq ($(PLATFORM),CMPC)这个语句中选择LINUX_SRC为(4LINUX_SRC =/home/chen/Hi3515_SDK_V1.0.2.0.c1/source/os/linux-2.6.24;注意这里LINUX_SRC的指是你买板子的时候商家提供给我们的SDK里面对应的内核,而不是unbutu的内核;

       这里需要注意驱动的makefile里的(5)这个地方,他不是一般的gcc,而是用了make,开始的时候看不明白,以前看的简单的makefile里面这里都是用的gcc来编译文件的,这里怎么会用make,开始以为这里错了,后来查了之后才知道,make -C $(LINUX_SRC)  SUBDIRS=$(shell pwd)  modules”的意思是到LINUX_SRC这里路径下寻找Makefile并执行,后面两个是传进Makefile的参数;

        这样就需要我们自己去查看LINUX_SRC目录下的那个Makefile了,需要修改里面的gcc编译器(将其指定为我们的交叉编译器)。

        以下是内核的makefile的一段代码:

......

(a):   HIL_CONFIG_FILE=.hil_config
......

(b):   SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
                  -e s/sh[234].*/sh/ )


(c):   ARCH        ?= $(shell if [ -f $(HIL_CONFIG_FILE) ]; then \
                cat $(HIL_CONFIG_FILE) | grep ARCH= | sed -n s/ARCH=//p; \
            else \
                echo $(SUBARCH); \
            fi)

(d):   CROSS_COMPILE    ?= $(shell if [ -f $(HIL_CONFIG_FILE) ]; then \
                cat $(HIL_CONFIG_FILE) | grep CROSS_COMPILE= | sed -n s/CROSS_COMPILE=//p; \
            fi)

        关于内核makefile的一个说明:

        这里的首先在(a)这里指定了一个文件(以点开头的文件在linux中是隐藏文件);

        在(b)处指定了我们系统的架构;

        在(c)处的意思是如果在目录下存在(a)中指定的文件.hil_config则将ARCH配置成.hil_config中指定的ARCH,否者指定为系统的ARCH,即在(b)中得到的SUBARCH

        在(d)处和(c)的意思基本一样,如果存在.hil_config这个文件则将交叉编译器CROSS-COMPILE指定为.hil_config文件里指定的交叉编译器。


移植过程中出现的问题以及解决方法:

问题1:当我指定linux内核为ubuntu的内核,使用系统gcc编译器时生成的RT73.ko在ubuntu系统上可以insmod。但是指定为sdk中的内核,使用交叉编译器时能生成的Rt73.ko文件在开发板上insmod的时候提示“insmod: cannot insert 'rt73.ko': invalid module format”,最后分析了一下,可能原因主要有三个:

(I)gcc问题
    未正确指定交叉编译器;
(II)内核问题
    make时出现的警告:Module.symvers is missing(但是使用make oldconfig && make prepare && make scripts也无法生成);
(III)板子上的内核与使用的内核不兼容的问题。

        第(I)个原因:开始的时候,由于不知道在上面(a)中提到的文件是一个隐藏文件,以为系统里没有这个文件,再看到内核里面的注释,以为是“make CROSS_COMPILE=ia64-linux-”这样的一种方式指定交叉编译器,结果生成的insmod还是无法insmod,而且是不管“make CROSS_COMPILE=其他什么变量”都能生成一个rt73.ko,之后断定不是以这种方式指定交叉编译器的。最后在朋友的帮助下,知道了在linux里以点开头的文件都是隐藏文件才知道,实际上交叉编译器已经由这个隐藏文件指定好了,排除第一个原因;

        第(III)个原因:到串口终端下执行“cat /proc/version”,发现开发板上内核和我指定的内核都是linux-2.6.24,所以再排除第(III)种因素;

       第(II)个原因:内核缺少Module.symvers这个文件,看网上说是用“make oldconfig && make prepare && make scripts”,这个命令可以生成这个文件的,但是我的在执行之后却没有生成。最后是通过编译内核才生成了这个文件。

       编译内核的步骤:

       首先,执行make menuconfig来配置内核(即指定内核的配置文件)

             配置内核的操作如下:
             hisilicon$cd source/os/linux-2.6.24
              hisilicon$make mrproper
              hisilicon$make menuconfig
              其中“make mrproper”为可选,用户可直接通过“make menuconfig”进行内核配置。
              如果执行了 make mrporper,必须重新加载.config文件,具体步骤如下:
              步骤 1 执行 make menuconfig。
              步骤 2 选择“Load an Alternate Configuration File”菜单项。
              步骤 3 输入 arch/arm/configs /hi3515v100_full_release_defconfig。
              步骤 4 选择需要的模块。
              步骤 5 保存并退出。
        然后,执行make编译内核(这个过程需要的时间比较长,我花了大概20分钟,具体要看电脑配置)

        在执行了上面两个步骤之后,便会生成之前缺失的Module.symvers,现在再编译驱动的时候便能够生成一个能够在开发板上insmod的rt73.ko驱动文件了。


        在生成rt73.ko驱动文件之后,需要将其拷贝到开发板上,我是通过nfs拷贝的,具体设置方法见博文“Ubuntu开启nfs并连接开发板”。

        然后在板子上执行下面的步骤(参考http://www.cnblogs.com/rockstone/archive/2010/02/09/1666761.html):

                  insmod rt73.ko
                  ifconfig eth0 down
                  iwconfig (会看到rausb0)
                  ifconfig rausb0 up
                  iwlist rausb0 scan (扫描附近AP)
                  iwconfig rausb0 essid "APName" (接入AP)
                  ifconfig rausb0 192.168.0.100 (配置IP)

        我的板子上没有iwconfig这个命令,可以自己移植这个命令,到网上或者我的csdn资源中下载wireless_tools.28.tar.gz,解压后修改makefile:
                  CC = arm-hismall-linux-gcc 
                  AR = arm-hismall-linux-ar
                  RANLIB = arm-hismall-linux-ranlib

          然后执行make clean 和make,最后把生成的iwlist iwconfig等拷贝到开发板的bin或者sbin目录下便可以使用了。



-------------------------------------------华丽的分割线----------------------------------------------

编译内核时出现的问题及解决办法:

        一般来说卖给我们班子的人会提供给我们一个健壮的内核,至少肯定能够make通过,但是他们给我的sdk里的内核却有问题(哎,遇上不良商家了),make的时候出现以下的错误;

drivers/ata/ahci.c:618: error: `bfin_atapi_suspend' undeclared here (not in a function)
drivers/ata/ahci.c:618: error: initializer element is not constant
drivers/ata/ahci.c:618: error: (near initialization for `hi3515_ahci_driver.driver.suspend')
drivers/ata/ahci.c:619: error: `bfin_atapi_resume' undeclared here (not in a function)
drivers/ata/ahci.c:619: error: initializer element is not constant
drivers/ata/ahci.c:619: error: (near initialization for `hi3515_ahci_driver.driver.resume')

        我问了他们的售后之后,他们也没给我们解决(哎,这是什么售后呀),最后只有自己和身边朋友一起解决了。

解决方法如下:

        其中使用到的软件工具是source insight3.5。

        在source insight中建立一个工程,打开内核源码,然后Add All文件的时候需要选中“Recursively add lower sub-directories”;

        然后执行Project-->Rebuild Project ...   (使所有的文件关联起来,这样在查找某个变量的时候便会在所有打开的文件中查找);

        然后根据错误提示跳到ahci.c文件的第618行

         #ifdef CONFIG_PM
         .suspend      = bfin_atapi_suspend,
         .resume        = bfin_atapi_resume,
         #endif

        这个是ATA硬盘里的Power Management相关的代码。根据warning的意思是这里缺少bfin_atapi_suspendbfin_atapi_resume这两个函数。我们采用了两种方法来解决这个问题。

       去掉内核配置中的这个东东的步骤是:

        方法1:进入内核的drivers/ata/目录,打开makefile,看到“obj-$(CONFIG_SATA_AHCI)        += ahci.o”;

             打开drivers/ata/目录下的Kconfig,搜索SATA_AHCI,然后将这个下面的几行代码注释掉;   
                   tristate "AHCI SATA support"
               #    depends on PCI
                    help
                     This option enables support for AHCI Serial ATA.
  
                   If unsure, say N.   

                      在内核目录下重新make menuconfig配置保存刚才修改的内核(只需要进入menuconfig,然后保存退出)

             之后再make内核,这样能够去掉之前出现的错误,但是后来发现又出现了新的类似错误,于是觉得这个不是解决问题的根本方法,于是采用了下面的方法2。

        方法2:在ahci.c的618行的bfin_atapi_suspend右击,选择“jump to definition”,这时可以发现在另一个文件里有这 两个函数的定义,于是乎将这两个函数拷贝到achi.c里面(放到出现错误位置的上面)。之后我在make内核的时候便用过了编译,最终生成了我们需要的Module.symvers文件。



你可能感兴趣的:(linux)