一 开发环境:
(1)主机:vmware8+fedora14,内核版本为2.6.35,主机自带GCC版本4.5。(这两点很重要,所有的问题都与这两个因素有关)。
(2)目标机:S3C6410(arm11)
(3)目标机内核:linux2.6.24
(4)交叉编译工具:arm-linux-gcc-4.2.2
二 搭建交叉编译环境:
首先搭建PC上的编译环境,因为编译的驱动是在板子上运行的,第一步当然需要安装交叉编译器,即arm-none-linux-gnueabi-gcc等或者是arm-linux-gcc等。其实比较简单,可以从网上下载或者光盘中得到。
得到编译器的包后拷贝到/usr/loca/ 解压缩,关键的步骤是设置环境变量,即使其他程序能找到arm gcc,有好几方式设置环境变量:
(1) 用文本编辑器打开/etc/profile
在最后面加上
ARM_PATH=/usr/local/arm-2009q1/bin/ #(这个是你编译器的路径)
PATH=$ARM_PATH/bin:$PATH
export ARM_PATH
需要注销重新登录
(2)修改.bashrc文件
这种方法更为安全,它可以把使用这些环境变量的权限控制到用户级别,如果你需要给某个用户权限使用这些环境变量,你只需要修改其个人用户主目录下的.bashrc文件就可以了。
加的东西和上面一样也需要注销重新登录,生效。
(3)本人用的是第三种方法
打开/etc/environment 在最后一项添加:/usr/local/arm-2009q1/bin/ 各项间以:分隔,还是注销重新登录。
试验一下,在终端中输入arm- 然后tab键,如果能补全就ok了。
三 内核源码树构建(最难的部分):
(1)因为要把驱动编译后放到目标机上运行,所以交叉编译调用的库文件要是目标机的版本的内核库文件。
(2)一般从网上下载的内核源码是没有编译过的,没有编译过的内核源码是无法进行模块开发的。第一点,就是源码树中有相应的头文件和函数的实现,没有源码树,你哪调用去呢?(PC上编译的时候内核有导出符号,系统中有头文件,这样就可以引用内核给你的接口了,但是只能编译你PC上版本的内核可加载的模块)。第二个,内核模块中会记录版本号的部分,需要记录版本号的原因是不同的内核版本之间,那些接口和调用可能会有比较大的差异,因此必须要保证你的代码和某个特定的内核对应,这样编译出来的模块就可以(也是只能)在运行这个内核版本的Linux系统中加载,否则一个很简单的异常就会导致内核崩溃,或者你的代码根本无法编译通过(接口名变了)。
所以,要根据目标机的平台和环境以及要用到的模块来构建内核源码树。网上有大堆的教程来升级主机的内核(不是放到目标机上的),但是嵌入式linux的平台五花八门,不可能有一个统一的编译过程。
这里,介绍一个我用的很简单的方法。
(1)准备内核源码
最好用购买开发板或核心板附带的源码包。进入/usr/src/目录下解压即可,目录可自己选择。
(2)make clean
删除所有的编译生成文件,再加上各种备份文件。而make mrproper会清理掉配置文件:
如默认的.config文件和厂家自带的XXX.config。所以要慎重!!!
(3)配置内核
有好几种方法,我个人推荐用make menuconfig,图形化配置内核很方便。当然这种方法依赖一个库,要提前装好ncurse库。
如果从头开始配置内核,难度相当大。所以我load开发板源码包里提供的该平台的配置文件XXXX.config。在此基础上根据需要适当修改即可。
cp xxx.config .config
把别人的配置文件拷贝给自己用。
我之前开发SPI驱动,load源码包自带的arm平台的配置文件,在device drivers里单独配置好SPI选择项。
配置好内核后,可以查看.config文件,查看自己的配置是不是合理。
(4)编译内核
切入源码目录。
make或者make zImage或者makebzImage根据需要选择。
问题又来了!!
编译内核调用的是主机的GCC,而主机的GCC是否兼容目标机linux的makefile是一个很头疼的问题。没办法,只能出现一个问题解决一个问题。
编译成功后,默认生成的代码树就在源码目录。源码说明文档里提供了一种将内核源码树导出到指定路径的方法:在所有命令后加入参数 O=/xx/xx/
四 调用内核源码树和交叉编译工具
CC:=/usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-gcc-4.2.2
ifneq ($(KERNELRELEASE), )
candrv-objs := mcp2510.o spi_control.o
obj-m :=candrv.o
else
PWD :=$(shell pwd)
#KDIR :=/usr/local/linux-2.6.24
KDIR :=/usr/src/linux-2.6.24
all:
$(MAKE)-C $(KDIR) M=$(PWD)
clean:
rm-rf .*.cmd *.o *.mod.c *.ko .tmp_versions
endif