1). 内核源码的配置项
在linux内核源码目录下,进行配置时:
make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
上面命令执行,它又会调用:
scripts/kconfig/mconf Kconfig //其中"scripts/kconfig/mconf"是一个专门在终端上显示界面的程序
// "Kconfig"是在源码目录下的文件,传递给mconf程序,让mconf根据"Kconfig"里面的内容产生相应的配置项.
//也就是说如要在linux内核里增加自己驱动的配置项时,只需要修改Kconfig文件里的内容即可.
//配置完成后,最终的内核配置结果存放在linux内核源码目录下的".config"里
2). Kconfig语法
基础语法1:
config 关键字A
类型 "提示字符" if 关键字B // if表示依赖关键字B项, 如果B项不选中,则A项不会显示出来
default y/m/n //默认值 y编进内核 m编为模块 n不编译
help
帮助信息
基础语法2:
config 关键字C
depends on 关键字D && 关键字E && 关键字F
类型 "提示字符"
类型有: bool tristate hex string int
//////////////
增加菜单项:
menu "菜单名" //增加一个菜单
config ...
config ...
endmenu
/////////////
必须选择一项的配置项:
choice
prompt "选项名"
default 关键字 //默认选中的项
config 关键字
bool/tristate "提示"
config ...
config ...
endchoice
///////////////////
menuconfig 与config用法一样
区别在: menuconfig如有子项依赖的话, 则子项在下级菜单里
config不管依赖关系怎样, 都是在并列的菜单项里
3). 增加我们自己的驱动配置项, 通常应是在设备驱动里
Kconfig里面可通过”source xxx/xxx/Kconfig”调用其它目录的Kconfig
在内核源码的drivers/目录下创建一个"0mydrvs"子目录, 里面存放我们自己的驱动源码.
把前面符号导出的源码放进0mydrvs目录里:
myfunc子目录装着myfunc.c 用于提供全局函数"myfunc"
usage子目录装着test.c,调用"myfunc"的测试代码
在linux内核里应用两个配置项来表示这两个驱动模块, 而且它们有依赖关系.
在linux内核里几乎每个目录里都有Kconfig, Kconfig文件由它的上一级目录的Kconfig里"source"调用.
//////////////
在0mydrvs目录里的Kconfig内容:
source "drivers/0mydrvs/myfunc/Kconfig"
source "drivers/0mydrvs/usage/Kconfig"
在0mydrvs目录下的myfunc子目录里的Kconfig内容:
config MYFUNC
tristate "configuration of myfunc"
default y
help
help of myfunc
在0mydrvs目录下的usage子目录里的Kconfig内容:
config USAGE
tristate "test of myfunc"
depends on MYFUNC
help
this is a test of myfunc
最后,不要忘了在内核源码drivers目录里的Kconfig增加调用0mydrvs里的Kconfig.
在drivers目录里的Kconfig增加语句:
source "drivers/0mydrvs/Kconfig"
/////////////
通过"make menuconfig ..."选上这两个配置项后,在.config文件里可查看到:
...
995 CONFIG_MYFUNC=m
996 CONFIG_USAGE=m
4). 驱动源码的编译.
前面加Kconfig仅仅多了两个配置项,最终也就是在”.config”文件里多两项内容.
编译还是需要用Makefile来指定编译的, 但是Makefile里应当由.config里的相应的关键字内容来决定是否编译,及是编进内核还是编成模块.
在linux内核里又是每个目录里都有Makefile文件, 由它的上一级目录里的Makefile文件里调用.
在0mydrvs目录里的Makefile内容:
obj-y += myfunc/
obj-y += usage/
在0mydrvs目录里的myfunc子目录的Makefile内容:
obj-$(CONFIG_MYFUNC) += myfunc.o
在0mydrvs目录里的usage子目录的Makefile内容:
obj-$(CONFIG_USAGE) += test.o
最后在内核源码的drivers目录的Makefile增加调用0mydrvs里的Makefile.
在drivers目录里的Makefile增加语句 :
obj-y += 0mydrvs/
5). 编译的操作:
如果配置项是编进内核镜像的话, 只要做下面这步就可以了:
make uImage ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
// 编译好后,更换uImage后启动系统时,就会看到相应的打印输出
如果配置项是编成模块的话,除了做上面步骤外,还需要:
make modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
如果编译出的模块很多的话,还可以:
make modules_install INSTALL_MOD_PATH=板文件系统根目录/ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
//////////////////////
驱动模块在内核里的编译的好处:
在查看到驱动模块间的依赖关系。如:
modinfo drivers/0mydrvs/usage/test.ko
filename: /disk3/myown/h3/orangepi_sdk/source/linux-3.4.112/drivers/0mydrvs/usage/test.ko
license: GPL
depends: myfunc
intree: Y
vermagic: 3.4.112 SMP preempt mod_unload ARMv7 p2v8
可以看出test.ko是依赖myfunc.ko的,当用"modprobe test"加载test.ko时会自动把依赖的驱动模块也加载上.
//注意,用modprobe加载驱动模块必须是用"make modules_install ...."生成的.