增加驱动源码到内核
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"里
Kconfig语法:
类型有:
bool:布尔(选或不选)
tristate:三态(编进内核或编成模块或不编)
hex:十六进制数
string:字符串
int:整型
基础语法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 //depends on表示依赖关键字D, E, F项,如果这些项有其中一项不选中,则C项不会显示出来(可不写依赖)
类型 "提示字符"
增加菜单项:
menu "菜单名" //增加一个菜单
config ...
config ...
...
endmenu
必须选择一项的配置项:
choice
prompt "选项名"
default 关键字 //默认选中的项
config 关键字
bool/tristate "提示"
config ...
config ...
....
endchoice
menuconfig与config用法一样,区别在:menuconfig如有子项依赖的话,则子项在下级菜单里,config不管依赖关系怎样,都是在并列的菜单项里
在linux内核里应用两个配置项来表示这两个驱动模块,而且它们有依赖关系。
在linux内核里几乎每个目录里都有Kconfig,Kconfig文件由它的上一级目录的Kconfig里”source”调用。
增加我们自己的驱动配置项(Kconfig里面可通过“source xxx/xxx/Kconfig”调用其它目录的Kconfig):
1.在内核源码的drivers/目录下创建一个"mydrives"子目录(里面存放我们自己的驱动源码)
2.在mydrivers目录下增加我们的驱动源码:
(1)创建myfunc子目录写myfunc.c(用于提供全局函数"myfunc"):
myfunc.c的内容:
#include <linux/init.h>
#include <linux/module.h>
void myfunc(char *str)
{
printk("in my func\n");
printk("%s\n", str);
}
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(myfunc);
(2)创建mytest子目录写mytest.c(调用"myfunc"函数的测试代码):
mytest.c的内容:
#include <linux/init.h>
#include <linux/module.h>
extern void myfunc(char *str);
int num = 1000;
static int __init test_init(void)
{
myfunc("in test to call the extern func of myfunc");
printk("in test : num is %d\n", num);
printk("test init success\n");
return 0;
}
static void __exit test_exit(void)
{
printk("test exited\n");
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
(3)分别在myfunc子目录和mytest子目录写Kconfig文件:
myfunc子目录里的Kconfig内容:
config MYFUNC
tristate "configuration of myfunc"
default y
help
help of myfunc
mytest子目录里的Kconfig内容:
config MYTEST
tristate "test of myfunc"
depends on MYFUNC
help
this is a test of myfunc
(4)写mydrivers目录Kconfig文件:
mydrivers目录里的Kconfig内容:
source "drivers/mydrivers/myfunc/Kconfig"
source "drivers/mydrivers/mytest/Kconfig"
(5)最后,不要忘了在内核源码drivers目录里的Kconfig增加调用mydrivers里的Kconfig
在drivers目录里的Kconfig增加语句:
source "drivers/mydrivers/Kconfig"
注意:通过"make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-"选上这两个配置项后,在.config文件里可查看到:
CONFIG_MYFUNC=y/m/n
CONFIG_MYTEST=y/m/n
编译还是需要用Makefile来指定编译的,但是Makefile里应当由.config里的相应的关键字内容来决定是否编译(即编进内核或编成模块或不编译)
在linux内核里又是每个目录里都有Makefile文件,由它的上一级目录里的Makefile文件里调用
3.写Makefile文件:
(1)在mydrivers目录里的Makefile内容:
obj-y += myfunc/
obj-y += mytest/
(2)在mydrivers目录里的myfunc子目录的Makefile内容:
obj-$(CONFIG_MYFUNC) += myfunc.o
(3)在mydrivers目录里的mytest子目录的Makefile内容:
obj-$(CONFIG_MYTEST) += mytest.o
(4)最后在内核源码的drivers目录的Makefile增加调用mydrivers里的Makefile:
在drivers目录里的Makefile增加语句:
obj-y += mydrivers/
4.写好xxx.c、Kconfig、Makefile后,编译:
(1)如果配置项是编进内核镜像:
make uImage ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
//编译好后,更换uImage,重启系统时,就会看到相应的内容输出
(2)如果配置项是编成模块:
make uImage ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
make modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
如果编译出的模块很多的话,可以通过以下命令写进文件系统:
make modules_install INSTALL_MOD_PATH=sd卡挂载目录(板文件系统根目录)/ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
//更换uImage,将模块拷贝到板文件系统,通过加载或卸载驱动,即可看到相应的内容输出
注意:用modprobe加载驱动模块必须是用”make modules_install INSTALL_MOD_PATH=sd卡挂载目录(板文件系统根目录)/ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-“生成的