Linux内核中增加一个新的驱动模块

开发环境

开发板: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:


    
  1. #include <linux/module.h> //所有模块都需要的头文件
  2. #include <linux/init.h> // init&exit相关宏
  3. #include <linux/kernel.h>
  4. MODULE_LICENSE( "GPL");
  5. MODULE_AUTHOR( "baoli");
  6. MODULE_DESCRIPTION( "hello world module");
  7. static int __init hello_init(void)
  8. {
  9. printk(KERN_WARNING "hello world.\n");
  10. return 0;
  11. }
  12. static void __exit hello_exit(void)
  13. {
  14. printk(KERN_WARNING "hello exit!\n");
  15. }
  16. module_init(hello_init);
  17. module_exit(hello_exit);

Makefile:

obj-$(CONFIG_HELLO) += hello.o
    

Kconfig:


    
  1. menu "HELLO TEST Driver "
  2. comment "HELLO TEST Driver Config"
  3. config HELLO
  4. tristate "hello module test"
  5. default m
  6. help
  7. This is the hello test driver --by baoli.
  8. endmenu

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. 问题及解决

make menuconfig 出现 endmenu in different file than menu

1)问题描述

添加一个驱动,然后在内核的顶层目录进行如下操作

make menuconfig

出现了如下错误提示:

'endmenu' in different file than 'menu' 

2)解决方案

在添加的驱动程序目录中,在Kconfig文件内

menu "Test Driver" config CONFIG_TEST     bool "Test support" endmenu

注:在“endmenu” 下必须留一个空行。即 "endmenu" 后输入一个回车,保存。

 

 

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页