22、TSP内核配置:Kconfig配置、Makefile编写、模块编译
好,咱们今天聊聊TSP驱动在内核里是怎么“注册”进去的。说白了,就是让Linux内核知道“嘿,这儿有个触摸屏驱动,你得编译它、加载它”。
这部分工作,我把它分成三块:Kconfig配置、Makefile编写、以及模块编译。这三块是连着的,缺一个都不行。我刚开始接触内核驱动时,就吃过这个亏——Kconfig写对了,Makefile忘了加,结果make menuconfig里死活看不到我的驱动选项。嗯,这种坑,咱们今天一并填上。
Kconfig配置:给驱动一个“开关”
Kconfig是内核的配置系统。你运行make menuconfig时看到的那些菜单,就是Kconfig文件定义的。我们要做的,就是给TSP驱动加一个配置项,让开发者可以选择“编译进内核”还是“编译成模块”。
我个人习惯把TSP驱动的Kconfig放在drivers/input/touchscreen/目录下。打开这个目录下的Kconfig文件,添加如下内容:
config TOUCHSCREEN_TSP
tristate "TSP Touchscreen support"
depends on I2C
help
Say Y here if you want to support TSP touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here.
The module will be called tsp.ko.
这里有几个关键点:
- tristate:表示三态——Y(编译进内核)、M(编译成模块)、N(不编译)。触摸屏驱动一般选M,方便调试和更新。
- depends on I2C:TSP大部分走I2C总线,所以依赖I2C子系统。如果你用的SPI,就写
depends on SPI。 - help:写清楚这个驱动是干什么的。别偷懒,以后你自己回头看代码时,help信息能救命。
default n。为什么?因为默认关闭,避免新手一不留神把驱动编进内核,结果硬件没接好导致系统启动卡死。安全第一。
Makefile编写:告诉编译器怎么干活
Kconfig只是定义了“开关”,Makefile才是真正告诉编译器“哪些文件要编译、怎么编译”的地方。同样在drivers/input/touchscreen/目录下,找到Makefile,添加一行:
obj-$(CONFIG_TOUCHSCREEN_TSP) += tsp.o
这行代码的意思是:如果CONFIG_TOUCHSCREEN_TSP被配置为Y或M,就编译tsp.o。如果配置为N,这行就相当于被注释掉了。
如果你的驱动由多个源文件组成,比如tsp_core.c、tsp_i2c.c、tsp_fw.c,可以这样写:
obj-$(CONFIG_TOUCHSCREEN_TSP) += tsp.o
tsp-objs := tsp_core.o tsp_i2c.o tsp_fw.o
这里tsp-objs指定了最终生成tsp.o需要哪些目标文件。内核的构建系统会自动把它们链接到一起。
tsp-core.c,但Makefile里写的是tsp_core.o。内核编译时找不到文件,报错信息还特别隐晦。折腾了半天才发现是下划线和连字符的问题。所以,文件名和Makefile里的名字必须完全一致,包括大小写和分隔符。
模块编译:从源码到.ko文件
Kconfig和Makefile都准备好了,接下来就是编译。有两种方式:
方式一:在内核源码树内编译
如果你有完整的内核源码,并且已经配置过(比如运行过make defconfig或make menuconfig),直接:
make modules
make modules_install
内核构建系统会自动扫描所有Makefile,找到obj-$(CONFIG_TOUCHSCREEN_TSP)对应的文件,编译生成tsp.ko。
方式二:外部模块编译(我最常用的方式)
实际项目中,我们往往不编译整个内核,只编译自己的驱动模块。这时候用外部模块编译:
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
这条命令的意思是:到内核构建目录(-C参数)去找头文件和Makefile规则,然后编译当前目录(M=$(pwd))下的模块。
编译成功后,你会看到:
Building modules, stage 2.
MODPOST 1 modules
CC [M] /home/user/tsp/tsp.mod.o
LD [M] /home/user/tsp/tsp.ko
嗯,看到tsp.ko生成,心里就踏实了。
加载与测试
模块编译好了,怎么用?
- 加载模块:
sudo insmod tsp.ko - 查看模块信息:
modinfo tsp.ko(会显示作者、描述、依赖等) - 卸载模块:
sudo rmmod tsp - 查看内核日志:
dmesg | tail(看驱动有没有打印信息)
insmod: ERROR: could not insert module tsp.ko: Unknown symbol。这是因为模块依赖的某个内核符号没有导出。解决办法:检查/proc/kallsyms里有没有你调用的函数,或者用modprobe代替insmod,它会自动处理依赖。
知识体系图
下面这张图总结了TSP内核配置到模块编译的完整流程:
这张图从左到右展示了从Kconfig定义、Makefile编写,到两种编译方式,最终生成tsp.ko并加载测试的完整链路。你想想看,每一步都环环相扣,少了哪个环节,驱动都跑不起来。
总结一下
Kconfig是“开关”,Makefile是“配方”,编译是“烹饪”。三者配合好了,你的TSP驱动才能顺利变成内核的一部分。我个人建议初学者先从外部模块编译开始,这样不用每次修改代码都重新编译整个内核,省时间。
嗯,这部分内容就到这里。记住:配置无小事,一个字母错了,可能就要折腾半天。细心一点,后面会省很多事。