Chinaunix首页 | 论坛 | 博客
  • 博客访问: 486587
  • 博文数量: 42
  • 博客积分: 2100
  • 博客等级: 大尉
  • 技术积分: 580
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-07 21:07
文章分类

全部博文(42)

文章存档

2011年(1)

2010年(18)

2009年(16)

2008年(7)

分类: LINUX

2010-10-25 12:26:59

网上有好多关于驱动的Makefile怎么写,驱动程序怎么运行,为什么驱动会没有main等等问题的问题的问题。下面我也给出我的驱动Makefile模板,这些东东都是在书籍和人家的研究成果上改进而来的,至于如何使用、怎么修改成自己的,大家就随意好了。

驱动测试有两种方式,一为内核树之内,一为内核树以外,前者有点复杂,涉及到将驱动放到合适的内核树目录,修改相应的Makefile以及Kconfig文件,不过,天下无难易之事,为之,难亦不难了;后者所做的劳动就不用那么多了,网上很多是使用这种方法,鄙人也随大流了。这个Makfile只适合于后者,特此说明。此外,内核的Makefile跟一般的应用程序的Makefile不太一样,就像驱动程序跟应用程序,内核头文件跟应用程序头文件等等,没必然关系,或者说是两码事,两者不能混为一谈。再有一点,驱动是跟内核打交道的,你的系统中必须有一个内核源代码,因为驱动的编译过程需要内核代码(或者只是头文件?未调查)

闲话不多说,下面列出的Makefileldd3的基础上添加如下东东:样式输出,各种不同提示信息颜色不同,可自由修改;将模块名称独立出来,可用于单独一个驱动源代码文件,也可用于多个驱动源代码文件;增加另外几个伪目标。下面逐一说明。

#################################################################

# file name: Makefile

# A simple Makefile for driver

# by Late Lee at

# based on LDD3 and other guys works

# copyleft @ 2010

#

#################################################################

 

############样式输出

### nothing, just for fun

OFFSET=\x1b[21G   # 21 col

COLOR1=\x1b[0;32m # green

COLOR2=\x1b[1;35m #

COLOR3=\x1b[1;31m # red

RESET=\x1b[0m

 

CLEAN_BEGIN=@echo -e "$(OFFSET)$(COLOR2)Cleaning up ...$(RESET)"

CLEAN_END=@echo -e "$(OFFSET)$(COLOR2)[Done.]$(RESET)"

 

MAKE_BEGIN=@echo -ne "$(OFFSET)$(COLOR1)Compiling ...$(RESET)"

MAKE_DONE="$(OFFSET)$(COLOR1)[Job done!]$(RESET)";

MAKE_ERR="$(OFFSET)$(COLOR3)[Oops! Error occurred]$(RESET)";

### nothing end here

 

CROSS_COMPILE=arm-linux-

CC := $(CROSS_COMPILE)gcc

LD := $(CROSS_COMPILE)ld

 

######### DEBUG部分

#DEBUG = y

ifeq ($(DEBUG), y)

       DEBFLAGS = -O -g

else

       DEBFLAGS = -O1

endif

 

# sth wrong here, don’t know why

#EXTRA_CFLAGS += $(DEBFLAGS) -I$(LDDINCDIR)

 

#########驱动模块名称以及源文件部分

# module name here

MODULE = GotoHell

# obj-m = module

# obj-y = into kernel

# foo.o -> foo.ko

ifneq ($(KERNELRELEASE), )

       obj-m := $(MODULE).o

 

# 驱动源代码文件,.o形式

# your obj file(s) here

       $(MODULE)-objs := foo.o bar.o

 

else

 

       KERNELDIR ?= /lib/modules/$(shell uname -r)/build

       PWD := $(shell pwd)

 

##########真正编译部分,添加了if语句

all:

       $(MAKE_BEGIN)

       @echo

       @if \

       $(MAKE) -C $(KERNELDIR) M=$(PWD) modules;\

       then echo -e $(MAKE_DONE)\

       else \

       echo -e  $(MAKE_ERR)\

       exit 1; \

       fi

endif

 

#####这个clean把生成的杂七杂八文件都删除,可用ls –al查看

clean:

       $(CLEAN_BEGIN)

       rm -rf *.cmd *.o *.ko *.mod.c *.symvers *.order *.markers \

       .tmp_versions .*.cmd *~

       $(CLEAN_END)

 

########伪目标部分

install:

       @echo -e "$(COLOR3)                   Note:"

       @echo -e "To install or not install,that is a question.$(RESET)"

 

modules:

       @echo -e "$(COLOR3)Do not need to do this.$(RESET)"

 

modules_install:

       @echo -e "$(COLOR3)Do not need to do this.$(RESET)"

 

.PHONY: all clean install modules modules_install

 

############# Makefile end here

 

1、样式输出:

OFFSET指定了那些提示信息的偏移,本想用个什么方法让它居中的,没找到,就直接指定到第21列了。

COLOR那几个是指提示信息的颜色,这个可以百度一下SHELL颜色,至于前景色,背景色怎么搭配才好看,那是阁下的事情了。

RESET将前面已经设置好的颜色统统还原到系统默认的。

再下来的几个提示信息,也是根据个人喜爱来修改。

本部分完全是optional,如果觉得占太多行不好看,完全可以去掉,省得看得眼花。

2、debug部分

一开始是用CFLAGS,结果不行,提示要使用EXTRA_CFLAGS,结果出了很多看不懂的错误信息,就不理它了,等以后真正用到调试再说,可能要重新配置内核才行。

3、驱动模块名称

网上好多都是obj-m:=hello.o这个形式,我一直想改掉,结果找到方法了。obj-m:=$(MODULE).o中的m是说要将这个驱动做成模块,使用insmod加载、rmmod删除。而在内核很多目录中的Makefile还可以看到另一种形式obj-y,意思是说将这个驱动搞到内核中去,跟着内核一起混,系统启动时它就加载了。关于:=就直接百度了,顺便可以把$@$<$^这几个给一起学习了。注意,$(MODULE).o.o文件,不是.ko文件,内核会帮你从hello.o创建一个hello.ko模块的。$(MODULE)-objs := foo.o bar.o是说这个模块由两个文件组成,这里也是.o文件。实际使用中需要修改模块名称以及模块源文件(其实算是目标文件)名称。

后面的不用说了,大家都知道的。

PC平台下编写驱动,需要修改的地方是该Makefile模板中红色黑体部分。如果在ARM平台,需要修改的是蓝色黑体部分。网上有资料显示,交叉编译命令为

$make ARCH=arm CROSS_COMPILE=arm-linux-

在实际测试过程,发现只要内核源代码正确指向在开发板中使用的内核源代码目录(当然,该内核的Makefile要修改才能编译出适合开发板的内核),直接输入make就可以了。谁对谁错,大家实地去考察一下便知结果。

关于Makefile是如何进行编译的,我在CSDN上找到一篇文章,来自sumsky的专栏,文章地址是http://blog.csdn.net/abc19842008/archive/2008/02/14/2095836.aspx。大家可以去看一下。下面这话是文章精华部分,现录于此。

当我们敲下make时,我们进入了这个权威的makefile二次。第一次进入makefile,发现KERNELRELEASE没有被设置时,于是她根据build这个符号链接定位内核源代码目录,然后进入default,开始第二个make,-C选项进入内核源代码目录,找到顶层的makefile,然后-M返回当前目录执行makefile文件,这就是第二次进入这个makefile,在这次,由于KERNELRELEASE变量已经定义,因此不需要进入else语言,在这里,obj-m:=hello.o这个语句和我们以前不是驱动程序中的makefile不同,在这里内核会帮你处理一切,这句话是告诉内核,需要从hello.o创建一个驱动模型(module)。

 

lwn上是这么说的:

The makefile will be read twice; the first time it will simply invoke the kernel build system, while the actual work will get done in the second pass. A makefile written in this way is simple, and it should be robust with regard to kernel build changes.

 

这个模板显示有点臃肿,但青菜萝卜,各有所爱,看久了就不觉得麻烦啰嗦了,而且能应用于驱动程序绝大部分场合。

本文适合那些喜欢捣鼓且有闲情逸致的人来研究,只追求结果者可以飘过。

 

后记:在某次实践中,在模块名称后多了一个空格,编译死活通不过。所以要特别注意这些很细节的细节,像shell脚本、C语言中用到的“\”后面也不能有空格。最后附图一张。

1 pc平台,使用fc9级过的2.6.27.25内核,直接输入make

2 pc下交叉编译,使用的2.6.30.2内核为移植到开发板中的内核,顶层Makefile已修改体系结构ARCH以及交叉编译器CROSS_COMPILE

阅读(1949) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~