Android平台的驱动编译跟普通的linux驱动编写有一点区别,主要区别在Makefile文件(需要交叉工具连DBG_CROSS_COMPILE)),这里以hello.c文件为例
#include <linux/module.h> static int __init hello_init(void) { printk(KERN_INFO "%s\n",__FUNCTION__); return 0; } static void __exit hello_exit(void) { printk(KERN_INFO "%s\n",__FUNCTION__); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL");
如果是普通的linux驱动,Makefile的写法为
ifeq ($(KERNELRELEASE),) KERNELDIR ?= /usr/src/linux-headers-4.4.0-24-generic/ PWD :=$(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers .PHONY: modules modules_install clean else obj-m:= hello.o endif
对于Android平台,Makefile的内容为
ifeq ($(KERNELRELEASE),) KERNELDIR_OUT ?= Android源码路径/kernel CROSS_COMPILE ?= Android源码路径/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi- PWD :=$(shell pwd) modules: $(MAKE) -C $(KERNELDIR_OUT) M=$(PWD) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers .PHONY: modules modules_install clean else obj-m:= hello.o endif
对于某些平台(qcom或者mtk),所有的生成文件都放在了Android源码的out目录下,所有内核源码路径要改成( Android源码根路径/out/target/product/具体cpu/obj/KERNEL_OBJ),对于64系统,要将ARCH=arm改成ARCH=arm64。其实,路径具体怎么填,参考编译源码时的打印信息即可,如
make -C kernel-3.18 O=/Android源码根路径/out/target/product/xxxx/obj/KERNEL_OBJ ARCH=arm64 CROSS_COMPILE=/Android源码根路径/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- ROOTDIR=/home/w/xxx modules
如果驱动模块由多个c文件组成,Makefile的编写如下
ifeq ($(KERNELRELEASE),) KERNELDIR_OUT ?= /home/w/M8974AAAAANLYD4275/out/target/product/msm8974/obj/KERNEL_OBJ CROSS_COMPILE ?= /home/w/M8974AAAAANLYD4275/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi- PWD := $(shell pwd) modules: #编译为驱动模块 $(MAKE) -C $(KERNELDIR_OUT) M=$(PWD) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) modules modules_install: $(MAKE) -C $(KERNELDIR_OUT) M=$(PWD) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) modules clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers .PHONY: modules modules_install clean else GT9xx_CORE_OBJS := gt9xx.o #指定驱动模块的核心文件(有init 和 exit) GT9xx_OTHER_OBJS := goodix_tool.o gt9xx_update.o #依赖文件 touchscreen-objs := $(GT9xx_CORE_OBJS) $(GT9xx_OTHER_OBJS) #xxx-objs := 指定驱动模块的所有依赖文件 obj-m := touchscreen.o #最终由xxx-objs链接生成touchscreen.o,再生成touchscreen.ko endif
如果要多个c文件分别编译成相应的驱动,Makefile的编写如下
ifeq ($(KERNELRELEASE),) KERNELDIR_OUT ?= /home/w/M8974AAAAANLYD4275/out/target/product/msm8974/obj/KERNEL_OBJ CROSS_COMPILE ?= /home/w/M8974AAAAANLYD4275/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi- PWD :=$(shell pwd) modules: $(MAKE) -C $(KERNELDIR_OUT) M=$(PWD) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers app .PHONY: modules modules_install clean else obj-m+= notifier_chain.o obj-m+= consumer.o obj-m+= producer.o endif