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

2019-07-12 16:13发布

一 开发环境: (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