MIPS 架构 Linux driver编译时遇到的问题

Linux kernel在V 2.6之后,modules的编译有些修改。不再是单独编译,而是将本module添加入:obj-m,并最终调用Linux Kernel Makefile 来编译modules.

任务一:

这次Sam需要在某一平台上编译Bluetooth driver.其实也就是BlueZ的Kernel部分。但这个平台Kernel Source Code做过精简,Bluetooth子系统已经被去掉了。所以Sam将Bluetooth driver从其它平台Kernel Source Code中抽出来,以Modules的形式加入。

1. 确定copy文件:

Sam需要声成bluetooth.ko, hci_usb.ko, l2cap.ko, hidp.ko。

2. 写Modules Makefile:

ifneq ($(KERNELRELEASE),)
        obj-m += hci_usb.o
        obj-m += hidp.o
        obj-m += l2cap.o
        obj-m += bluetooth.o
        bluetooth-objs := af_bluetooth.o hci_core.o hci_conn.o hci_event.o hci_sock.o hci_sysfs.o lib.o
        hidp-objs := core.o sock.o


else
        KERNELDIR ?=/home/sam/work/current/BCM/Kernel2.6
        PWD := $(shell pwd)

default:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

endif

这个结构很简单:手动调用Makefile时,会进入else.设置了Kernel目录和当前目录,然后利用 -C 进入Kernel Source顶层目录,调用的是Kernel 顶层Makefile。  M= 则让Kernel Makefile去编译这个目录内的Module。 则Kernel Makefile再次调用我们写的Makefile。这次因为KERNELRELEASE已被设置。所以在obj-m(所需要编译的Modules) 中添加了我们需要的这些项目。

又因为bluetooth.ko 和 hidp.ko是多个文件编译而成的,所以又作了以下动作:

bluetooth-objs := af_bluetooth.o hci_core.o hci_conn.o hci_event.o hci_sock.o hci_sysfs.o lib.o
hidp-objs := core.o sock.o #这两句也是从Bluetooth Kernel Makefile中抄来的。

3. 将所需要的.c, .h文件从Kernel 树中 copy到本目录内。

4. #make . 4个 ko文件就顺利生产了。

注意:如果当前Kernel树中有Bluetooth目录,则这个办法有缺陷。因为很可能两部分blueZ Version不同,造成很多struct 有变化,无法编译通过。

blueZ版本号: net/bluetooth/af_bluetooth.c中:version 就是。

任务二:

工作Linux Server机器上,不同平台的交叉编译工具有不少,所以Sam很不喜欢有人用export PATH=...的方式指定交叉编译器。这样很容易造成错误和误会。

Sam的办法是:每个人在写Makefile中,都用绝对路径指定所需要的cross comple. 但在编译Kernel时,就有问题了。需要去改动Kernel Makefile。这样很不方便。也觉得很硬,一直没有好的办法。

先说之前的办法:

一般是在 arch/*/Makefile中去强硬的修改CROSS_COMPILE。这样的问题是,如果ToolChain换了地点或者这份Source Code 换到另一台机器。就需要再去修改。让人很烦。

今天无意中看了一眼CROSS_COMPILE说明,才发现有非常好的办法:

#make CROSS_COMPLE="绝对路径"/mipsel-linux-

这样就很容易解决了上述问题。 当然,定义环境变量也能达到以上效果。

知识点1:

MIPS架构中的Endianess Selection.

MIPS架构中,有Little endian和Big endian. 所以,在针对MIPS架构的Kernel中,有配置大头或小头的选项。 Endianess selection-->

因为MIPS架构中分大小头,所以理所当然,交叉编译器也需要分大小头。

通常,MIPS交叉编译器中会有 mipsel-linux, mips-linux这2个目录。

其中,mips-linux是指 大头(Big endian)所使用的交叉编译器。

mipsel-linux是小头(little endian)所使用的交叉编译器。

知识点2:

Linux Modules版本察看:

Sam在提供bluetooth modules (ko文件)给另家公司时,反映kernel版本与modules版本不同。

kernel版本可以使用#uname -r 来查看。但Modules版本怎么看,一下子来不及查,就直接使用emacs 打开ko文件,去看了版本信息。呵呵,觉得太粗暴了。查了一下:

#modinfo xxx.ko 就可以查看。嘿嘿。

知识点3:

mipsel-linux-gcc找不到库位置的处理:

#mipsel-linux-gcc -Wl,-rpath-link -Wl,/home/sam/work/current/BCM/BCM7403/ToolChain/crosstools_sf-linux-2.6.12.0_gcc-3.4.6-21_uclibc-0.9.28-20050817-20070607/mipsel-linux/lib  test.c -o test

 

知识点4:

-rpath, -rpath-link 与 -L的区别。

当Link阶段,找不到库时,编译器会自动找几个地点(具体地点在libtool学习中有)

但 -L也是这个作用。

Sam猜想是这样的,如果显式的使用 -lxxx. 则 -rpath-link与 -L都可指定位置。

如果是c基本库,则只能使用-rpath, -rpath-link。

另外,-rpath, -rpath-link都是给link的,所以需要用 -W1,的形式传递给ld.

相关推荐