linux设备驱动以内核模块的形式出现,编写linux内核模块编程是学习linux设备驱动的先决条件。
在编译linux内核之前要先配置linux内核。每个板子都有其对应的默认配置文件,这些默认配置文件保存在arch/arm/configs 目录中。比如xilinx_zynq_defconfig作为zynq所使用的默认配置文件。
编译驱动有两种方法
第一种方法:linux 提供了这样的机制,这种机制被称为模块(Module)。将驱动代码编译成.ko 驱动模块,然后在linux系统下使用insmod或modprobe命令加载驱动模块之后进行测试;驱动开发工程师将驱动代码编译成.ko驱动模块可以很方便的进行驱动调试,所以在驱动调试阶段一般都选择将其编译为模块,这样修改驱动以后只需要编译一下驱动代码即可,不需要编译整个linux源代码;模块本身不被编译入内核映像,从而控制了内核的大小。模块一旦被加载,它就和内核中的其他部分完全一样。
1,编写Makefile文件,KDIR写入内核源目录
KDIR=/home/geyuxi/Desktop/zynq_linux/build/tmp/work/plnx_zynq7-xilinx-linux-gnueabi/linux-xlnx/4.14-xilinx-v2018.3+git999-r0/linux-xlnx-4.14-xilinx-v2018.3+git999
PWD := $(shell pwd)
CC = $(CROSS_COMPILE)gcc
ARCH =arm
MAKE =make
obj-m:=gt9xx.o
modules:
$(MAKE) -C $(KDIR) ARCH=$(ARCH) CROSS_COMPLE=$(CROSS_COMPILE) M=$(PWD) modules
clean:
make -C $(KDIR) ARCH=$(ARCH) CROSS_COMPLE=$(CROSS_COMPILE) M=$(PWD) clean
2,导入交叉编译器并设置环境变量
export CROSS_COMPILE=arm-linux-gnueabihf-
3,执行make,生成.ko文件
4,使用驱动文件,执行insmod *.ko。卸载驱动文件,执行rmmod *.ko
第二种方法:直接把驱动编译到内核中
为建立对模块的感性认识,编译驱动为内核模块。
1,修改Makefile
会看到很多 obj-$(CONFIG_TOUCHSCREEN_GT9XX) += goodix_gt9xx.o这种代码,是加入驱动代码到内核编译。CONFIG_XXX变量可以取3个不同的值:y、m、n;所以将$(CONFIG_XXX)替换之后也就是定义了三个变量 obj-y、obj-m、obj-n。obj-y 变量中所有的 xxxx.o 所对应的 xxxx.c 文件都会被编译进内核镜像;当在内核源码目录执行“make modules”编译内核模块的时候,obj-m 变量中所有的 xxxx.o 文件对应的 xxxx.c 源文件会被编译成.ko 驱动模块文件;而 obj-n 变量中所有的 xxxx.o 文件对应的 xxxx.c 源文件既不会编译进内核镜像文件,也不会编译成驱动模块。所以由此可以知道 CONFIG_XXX 好比是一个“选择器”,你可以选择将源文件编译进内核中,也可以选择编译成一个.ko 驱动模块文件,也可以不编译。
# SPDX-License-Identifier: GPL-2.0
# Makefile for the touchscreen drivers.
# Each configuration option enables a list of files.
wm97xx-ts-y := wm97xx-core.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_SX8654) += sx8654.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_ZET6223) += zet6223.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
obj-$(CONFIG_TOUCHSCREEN_GT9XX) += goodix_gt9xx.o
2,修改Kconfig
打开内核源码drivers每个目录下的Kconfig文件进行增改。
(1)config ASYNCNOTI是 CONFIG_ASYNCNOTI变量的配置项,用于配CONFIG_ASYNCNOTI变量的值是 y、m 还是 n。
(2)tristate表示三态,也就是可以将 CONFIG_ASYNCNOTI 变量的值设置为y、m 或者 n 中的任何一个,后边携带的字符串信息表示的是对该 config 配置项的一个描述信息。
(3)default y表示该配置项的默认值是 y,在 Kconfig 文件中添加配置项之后,当我们在内核源码目录执行“make menuconfig”的时候就可以通过图形化界面的方式对其进行配置了。
config TOUCHSCREEN_GOODIX
tristate "Goodix I2C touchscreen"
depends on I2C
depends on GPIOLIB || COMPILE_TEST
help
Say Y here if you have the Goodix touchscreen (such as one
installed in Onda v975w tablets) connected to your
system. It also supports 5-finger chip models, which can be
found on ARM tablets, like Wexler TAB7200 and MSI Primo73.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called goodix.
config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen"
depends on I2C
help
Say Y here if you have a ILI210X based touchscreen
controller. This driver supports models ILI2102,
ILI2102s, ILI2103, ILI2103s and ILI2105.
Such kind of chipsets can be found in Amazon Kindle Fire
touchscreens.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called ili210x.
3,menuconfig
在内核源码目录下执行命令进入到menuconfig配置界面:
make distclean // 清理整个工程
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- xilinx_zynq_defconfig // defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig // menuconfig
<*>尖括号里边的“*”符号表示该配置项默认是选中的,也就是配置为“y”;将光标移动到该配置条目上,分别按键盘上的“Y”、“M”、“N”键可以分别选择将该驱动编译进内核、编译成单独的驱动模块、不编译驱动源文件。将驱动编译进内核中,所以这里选“Y”即可!对于menuconfig界面中的每一个配置项,都可以查看它的help帮助信息