前面已经写好了字符驱动模板,接下来我们要将其编译成模板,并加载到内核。这里使用的开发板是正点原子 I.MX6ULL MINI版
目录
1、创建目录 /lib/modules/4.1.15-g3dc0a4b
四、解决 could not open /lib/modules/4.1.15-g3dc0a4b/modules.order
一、编译驱动模块
关于Makefile文件的分析,可以参考该文章中的单文件单模块编译:make modules 模块编译
KERNEL_DIR := /home/ubuntu/tool/linux-imx-kernel
CURRENR_DIR := $(shell pwd)
MODULE_NAME := chrdevbase # 定义模块名
obj-m := $(MODULE_NAME).o
build: kernel_modules
kernel_modules:
$(MAKE) -C $(KERNEL_DIR) M=$(CURRENR_DIR) modules # 编译生成模块文件
.PHONY:clean
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(CURRENR_DIR) clean
如果编译过程中出现了 “ Kernel configuration is invalid ” ,说明你所使用的内核源码没有经过编译,需要先将内核源码进行编译才能使用。
二、加载驱动模块
1、创建目录 /lib/modules/4.1.15-g3dc0a4b
内核默认去 /lib/modules/xxx 下找模块文件,其中 xxx 是内核版本,可以使用uname -r 命令查看。如果目录不存在,需手动创建
2、加载模块
加载模块有两种方法:insmod 和 modprobe 命令
- insmod 命令:只会加载指定路径下的某个模块,不会解决依赖
- modprobe:会帮忙解决依赖,也就是如果加载 a 模块需要 b 模块,那么会先加载 b 模块,再加载 a 模块
insmod 命令
命令格式:insmod xxx.ko
root@ATK-IMX6U:/lib/modules/4.1.15-g3dc0a4b# insmod chrdevbase.ko
[ 1292.681680] chrdevbase init!
modprobe 命令
使用modprobe命令之前需要先使用 depmod 命令,depmod 命令会扫描一下 /lib/modules/4.1.15-g3dc0a4b 目录下有哪些模块,并将结果写入到 modules.dep 文件中。
执行 depmod 以后会生成如下文件。如果出现了 could not open /lib/modules/xxx/modules.order,请参考本文结尾部分的解决方案。
接下来就是使用 modprobe 命令将模块加载到内核,加载模块不需要加上后缀!命令格式为:modprobe 模块名
root@ATK-IMX6U:/lib/modules/4.1.15-g3dc0a4b# modprobe chrdevbase
[ 2919.975599] chrdevbase init!
3、查看系统中存在的模块
直接输入 lsmod 命令便可查看当前系统中已经加载到内核的模块
4、手动创建设备节点文件
将模块加载到内核以后,并不会在 /dev 目录下生成对应的驱动文件,这里我们先使用一种临时方式来手动创建设备节点文件,后续等了解了设备树再改用其他方法
# mknod /dev/模块名 c 主设备号 次设备号
mknod /dev/chrdevbase c 200 0
- mknod:创建节点命令
- c:表示创建的设备节点是字符设备
- 200:表示主设备号(需要和模块中设置的保持一致)
- 0:表示次设备号
5、卸载模块(一开始先跳过)
因为下面我们要配合应用程序进行测试,这里先不卸载模块,等测试完毕我们再卸载模块,卸载模块也很简单,命令格式为:rmmod 模块名
root@ATK-IMX6U:/lib/modules/4.1.15-g3dc0a4b# rmmod chrdevbase
[ 2837.265342] chrdevbase exit!
三、编写应用程序
下面我们需要编写一个简单的应用程序来测试驱动是否能正常工作
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void printHelp()
{
printf("usage: ./chrdevbaseApp <driver_path>\n");
}
int main(int argc, char* argv[])
{
if (argc == 1)
{
printHelp();
return -1;
}
char* filename = argv[1]; // 位置0 保存的是 ./chrdevbaseApp
int fd = open(filename, O_RDWR);
if (fd < 0)
{
perror("open file failed");
return -2;
}
const char* txbuf = "hello, world";
write(fd, txbuf, strlen(txbuf));
char rxbuf[20] = {0};
read(fd, rxbuf, 20);
printf("%s\n", rxbuf);
close(fd);
return 0;
}
将该测试文件编译生成可执行文件 chrdevbaseApp,拷贝到 /lib/moduls/xxx 目录下,运行该文件,如果出现了下面四句话,说明驱动工作正常。
四、解决 could not open /lib/modules/4.1.15-g3dc0a4b/modules.order
根据提示,我们知道是因为modules.order 和 modules.builtin文件缺失。
正点原子的内核源码编译成功后,会在顶层目录下生成 modules.order 和 modules.builtin,我们只需把这两个文件拷贝到开发板的 /lib/modules/xxxx 目录下
参考文章:
Linux驱动编译报错ERROR: Kernel configuration is invalid怎么办_毛炳浩的博客-CSDN博客
imx6ull驱动开发经验_rmmod: error: ../libkmod/libkmod.c:514 lookup_buil_fhqlongteng的博客-CSDN博客