12. 添加驱动模块到Linux内核

大部分有修改内核需求的用户基本上都是对于驱动的修改或者是对于设备树的修改, 其中设备树目录在 arch/arm/boot/dts 目录下,设备树插件目录在 arch/arm/boot/dts/overlays 目录下, 驱动目录在ebf_linux_kernel/drivers下, 每个不同的驱动占用一个子目录,如char、block、 net、 mtd、 i2c等。

下面介绍如何往内核中添加一个简单的驱动模块,在drivers目录下存在一个 ebf_module目录,用于存放一些野火自己编写的驱动模块,我们将在这个目录下添加新的驱动模块, 在ebf_module目录下新建hello_module目录,并在hello_module目录下新建 hello_module.c 以及Makefile文件,目录结构如下所示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
.
├── dht11
│   ├── dht11.c
│   ├── dht11.h
│   ├── Makefile
│   └── test_app.c
├── ds18b20
│   ├── ds18b20.c
│   ├── ds18b20.h
│   ├── ds18b20.sh
│   ├── Makefile
│   └── test_app.c
├── hello_module
│   ├── hello_module.c
│   └── Makefile
├── infrared
│   ├── infra.c
│   ├── infra.h
│   ├── Makefile
│   └── test_app.c
├── Kconfig
└── Makefile

12.1. hello_module.c文件

hello_module.c文件为模块的主要内容,编写一些内容。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

static int __init hello_init(void)
 {
    printk(KERN_EMERG "[ KERN_EMERG ]  Hello  Module Init\n");
    printk( "[ default ]  Hello  Module Init\n");
    return 0;
}

static void __exit hello_exit(void)
{
    printk("[ default ]   Hello  Module Exit\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL2");
MODULE_AUTHOR("embedfire ");
MODULE_DESCRIPTION("hello world module");
MODULE_ALIAS("test_module");

12.2. hello_module/Makefile文件

hello_module/Makefile文件内容如下

1
 obj-$(CONFIG_HELLO_MODULE) := hello_module.o

12.3. Makefile文件

除了hello_module/Makefile文件之外还需要修改上一层Makefile的文件的内容, 添加内容如下

1
2
3
4
5
#core
obj-y += dht11/
obj-y += ds18b20/
obj-y += infrared/
obj-y += hello_module/

12.4. Kconfig文件

添加kconfig文件内容如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
menu "Embedfire Modules"

menuconfig EBF_MODULE
        bool "Embedfire Modules"

if EBF_MODULE

config EBF_DHT11
        tristate "dht11"

config DS18B20
        tristate "ds18b20"

config INFRARED
        tristate "infrared"

config HELLO_MODULE
        tristate "hello_module"

endif # EBF_MODULE

endmenu

12.5. 重新配置内核

执行如下命令, 找到hello_module的配置选项, hello_module配置路径为 Device Drivers > Embedfire Modules > Embedfire Modules 选择编译进内核的方式编译。

1
make menuconfig KCONFIG_CONFIG=arch/arm/configs/npi_v7_defconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

配置如下

arch/arm/configs/npi_v7_defconfig - Linux/arm 4.19.35 Kernel Configuration
 > Device Drivers > Embedfire Modules > Embedfire Modules ──────────────────────
  ┌─────────────────────────── Embedfire Modules ────────────────────────────┐
  │  Arrow keys navigate the menu.  <Enter> selects submenus ---> (or empty  │
  │  submenus ----).  Highlighted letters are hotkeys.  Pressing <Y>         │
  │  includes, <N> excludes, <M> modularizes features.  Press <Esc><Esc> to  │
  │  exit, <?> for Help, </> for Search.  Legend: [*] built-in  [ ] excluded │
  │ ┌──────────────────────────────────────────────────────────────────────┐ │
  │ │    --- Embedfire Modules                                             │ │
  │ │    <M>   dht11                                                       │ │
  │ │    <M>   ds18b20                                                     │ │
  │ │    <M>   infrared                                                    │ │
  │ │    <M>   hello_module                                                │ │
  │ │                                                                      │ │
  │ │                                                                      │ │
  │ │                                                                      │ │
  │ │                                                                      │ │
  │ │                                                                      │ │
  │ │                                                                      │ │
  │ │                                                                      │ │
  │ │                                                                      │ │
  │ │                                                                      │ │
  │ │                                                                      │ │
  │ └──────────────────────────────────────────────────────────────────────┘ │
  ├──────────────────────────────────────────────────────────────────────────┤
  │         <Select>    < Exit >    < Help >    < Save >    < Load >         │
  └──────────────────────────────────────────────────────────────────────────┘

选择保存后,重新执行 sudo ./make_deb.sh 编译新的内核deb安装包, 并通过以上介绍过方式将deb安装包重新安装到开发板上。 在开发板子上可看到 /lib/modules/4.19.35-carp-imx6/kernel/drivers/ebf_module/hello_module/hello_module.ko 文件。

12.6. 参考资料

kernel官网: https://www.kernel.org/

NXP内核源码: https://github.com/Freescale/linux-fslc