嵌入式linux驱动开发环境搭建(亲测成功)

时间:2021-05-02 23:38:00

一 开发环境:

(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