开发环境 开发板:A33-Vstar 开发板系统: Linux/arm 3.4.39 Kernel Ubuntu版本:Ubuntu14.04 ----------------------------------------------------
新增内核驱动,并可以通过make menuconfig配置。 内核完整路径:~/A33-Vstar/dragonboard/linux-3.4
1. 构建测试模块:hello 1.1 在linux-3.4/drivers/下新建目录hello cd linux-3.4/drivers/ mkdir hello 1.2 在hello/下新建hello.c Makefile Kconfig三个文件 hello.c:
Makefile:
Kconfig:
1.3 修改上一级目录的Kconfig和Makefile 进入linux-3.4/drivers/ 1)编辑Makefile,在后面添加一行: obj-$(CONFIG_HELLO) += hello/ 2)编辑Kconfig,在后面添加一行: source "drivers/hello/Kconfig" 注:某些内核版本需要同时在arch/arm/Kconfig中添加:source "drivers/hello/Kconfig"
2. make menuconfig配置 1)执行:make menuconfig ARCH=arm 2)选择并进入:Device Drivers选项 可以看到新增 HELLO TEST Driver选项 3)进入 HELLO TEST Driver选项 可以选择<m> <y> <n>,分别为编译成内核模块、编译进内核、不编译。
3. 编译 退出保存后进入:cd ~/A33-Vstar/dragonboard/ 执行:sudo ./build.sh 编译内核 1)如果选择编译成模块<m> 编译内核过程中,会有如下输出: LD drivers/hello/built-in.o CC [M] drivers/hello/hello.o CC drivers/hello/hello.mod.o LD [M] drivers/hello/hello.ko 2)如果选择编译进内核<y> 编译内核过程中,会有如下输出: CC drivers/hello/hello.o LD drivers/hello/built-in.o
编译完成后,drivers/hello/下新增hello.o和hello.ko,并且/linux-3.4/output/lib/modules/3.4.39/下也会有hello.ko。
4. 测试 4.1 编译成内核模块 下载镜像至A33开发板,使用minicom 超级终端和开发板连接。 cd /lib/modules/3.4.39 可看到hello.ko在此路径下。 1)inmod hello.ko dmesg | tail 显示hello world. 2)rmmod hello dmesg | tail 显示hello exit! 注:hello.ko已经被打包进系统镜像文件,在路径/lib/modules/3.4.39 下,所以下载安装镜像后不需要再重新拷贝镜像至开发板。 4.2 编译进内核 下载镜像至A33开发板,系统启动时在超级终端上显示加载信息:hello world.
5. 分析 5.1 source "drivers/hello/Kconfig" 在Kconfig中有类似语句:source "drivers/hello/Kconfig" 内核源码目录树中每一个Kconfig都会用source引入其所有子目录下的Kconfig,从而保证了所有的Kconfig项目都被包含进menuconfig中。这个也说明了:如果你自己在linux内核中添加了一个文件夹,一定要在这个文件夹下创建一个Kconfig文件,然后在这个文件夹的上一层目录的Kconfig中source引入这个文件夹下的Kconfig文件。 5.2 depends on 意思是本配置项依赖于另一个配置项。如果那个依赖的配置项为Y或者M,则本配置项才有意义;如果依赖的哪个配置项本身被设置为N,则本配置项根本没有意义。depends项会导致make menuconfig的时候找不到一些配置项。所以在menuconfig中如果找不到一个选项,但是这个选项在Kconfig中却是有的,则可能的原因就是这个配置项依赖的一个配置项是不成立的。depends依赖的配置项可以是多个,还可以有逻辑运算。这种时候只要依赖项目运算式子的结果为真则依赖就成立。 5.3 comment 用于定义一些帮助信息,出现在界面的第一行。 5.4 menu/endmenu menuconfig 1)menu用于生成菜单,其格式如下: menu "Floating poing emulation" config FPE_NWFPE config FPE_NWFPE_XP ............. endmenu menu之后的Floating poing emulation是菜单名,menu和endmenu间有很多config条目,在配置界面中如下所示: Floating poing emulation---> [] FPE_NWFPE [] FPE_NWFPE_XP
2)menuconfig有点类似menu,但区别就在于menu后面多了一个config,这个menu是可以配置的,如下图倒数第二行,前面比 menu类型多了一个<>,通过空格可以修改这个配置项的选中状态。而且从格式上来看,也是有区别的。格式如init/Kconfig中1131行: menuconfig MODULES tristate "Enable loadable module support"config if MODULES xx endif 也就是说,配置项是位于if和endif中。其中的部分就是MODULES子目录显示的内容。如果选中了MODULE,那么if和endif中的内容可以显示。如果没有定义,就只能进入一个空目录。 可以认为是menu和config的结合体,既在前面有选项,回车后也可以展开。 5.5 config config是构成Kconfig的最基本单元,其中定义了配置项的详细信息。 1) 每个config菜单项都要有类型定义: bool布尔类型、 tristate三态(内建、模块、移除)、string字符串、 hex十六进制、 int整型。 例如: config HELLO_MODULE bool "hello test module" bool 类型的只能选中或不选中,显示为[ ]; tristate类型的菜单项多了编译成内核模块的选项,显示为< > , 假如选择编译成内核模块,则会在.config中生成一个 CONFIG_HELLO_MODULE=m的配置,假如选择内建,就是直接编译成内核镜像,就会在.config中生成一个 CONFIG_HELLO_MODULE=y的配置。 2) default:默认值 比如config类型是tristate,则默认值可以是y 、m、n。 5.6 Kconfig和.config文件和Makefile三者的关联 经过menuconfig配置之后保存,就会在内核顶层目录下生成.config文件。 =y表示该配置将会被编译进内核,=m表示该配置需要单独编译成模块。 内核顶层makefile会调用.config文件,引用.config里的配置,进而选择性的编译内核驱动模块。 配置项被配置成Y、N、M会影响“.config”文件中的CONFIG_XXX变量的配置值。“.config”中的配置值(=y、=m、没有)会影响最终的编译链接过程。如果=y则会被编入(built-in),如果=m会被单独连接成一个”.ko”模块,如果没有则对应的代码不会被编译。那么这是怎么实现的?都是通过makefile实现的。 如makefile中:obj-$(CONFIG_DM9000) += dm9000.o, 如果CONFIG_DM9000变量值为y,则obj += dm9000.o,因此dm9000.c会被编译;如果CONFIG_DM9000变量未定义,则dm9000.c不会被编译。如果CONFIG_DM9000变量的值为m则会被连接成“.ko”模块。
6. 问题及解决
1)问题描述 添加一个驱动,然后在内核的顶层目录进行如下操作 make menuconfig 出现了如下错误提示: 'endmenu' in different file than 'menu' 2)解决方案 在添加的驱动程序目录中,在Kconfig文件内 menu "Test Driver" config CONFIG_TEST bool "Test support" endmenu 注:在“endmenu” 下必须留一个空行。即 "endmenu" 后输入一个回车,保存。
|
|