LV06-01-内核模块-01-编译与加载

本文主要是内核模块编译与加载的相关笔记。若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows版本 windows11
Ubuntu版本 Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
Linux开发板 正点原子 i.MX6ULL Linux 阿尔法开发板
uboot NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)
linux内核 linux-4.15(NXP官方提供)
Win32DiskImager Win32DiskImager v1.0
buildroot 2023.05.1版本
点击查看本文参考资料
分类 网址 说明
官方网站 https://www.arm.com/ ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档
https://www.nxp.com.cn/ NXP官方网站
https://www.nxpic.org.cn/NXP 官方社区
https://u-boot.readthedocs.io/en/latest/u-boot官网
https://www.kernel.org/linux内核官网
点击查看相关文件下载
分类 网址 说明
NXP https://github.com/nxp-imx NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库
https://elixir.bootlin.com/linux/latest/source 在线阅读linux kernel源码
nxp-imx/linux-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga NXP linux内核仓库tags中的rel_imx_4.1.15_2.1.0_ga
nxp-imx/uboot-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga NXP u-boot仓库tags中的rel_imx_4.1.15_2.1.0_ga
I.MX6ULL i.MX 6ULL Applications Processors for Industrial Products I.MX6ULL 芯片手册(datasheet,可以在线查看)
i.MX 6ULL Applications ProcessorReference Manual I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网)

驱动开发使用的都是之前buildroot构建的根文件系统。并且都是从tftp加载内核镜像和设备树,从nfs挂载根文件系统。

一、内核模块与加载基础

这部分可以看《01HQ课程体系里边的笔记》

二、ALPHA板实例

1. 在内核源码中编译

1.1 编译到linux内核镜像中

可以看这里:feat:模块在内核源码中 · f1d1fc2 · sumumm/imx6ull-linuxdriver-eg - Gitee.com。我们在linux图形配置界面将模块配置成编译到内核镜像中去:

image-20230806084742730

这样需要编译整个linux内核:

1
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j4

最终效果为:

image-20230806083434305

1.2 编译成独立的ko模块

可以看这里:feat:模块在内核源码中 · f1d1fc2 · sumumm/imx6ull-linuxdriver-eg - Gitee.com。我们在linux图形配置界面将模块配置成编译成独立的ko模块。

image-20230806084817293

这样需要重新编译一下内核和模块:

1
2
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j4 # 为了去掉之前编译到内核中的模块
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules -j4

然后就会在对应的源码目录中生成一个ko文件:

image-20230806090356456

2. 在内核源码外编译

我们在linux内核源码外创建驱动的文件夹和makefile文件,这样编译也会更快不需要编译整个linux内核。可以看这里:feat:模块在内核源码外 · 80cb88c · sumumm/imx6ull-linuxdriver-eg - Gitee.com,通过makefile文件,我们直接执行:

1
make ARCH=arm

这样就可以使用内核源码来编译我们的模块,编译完毕后,会得到如下文件:

image-20230806092501900

我们将ko文件拷贝到根文件系统,然后通过下边的命令加载:

1
insmod module_load.ko

就会看到有以下打印信息:

image-20230806092608108

三、加载命令

在《01HQ课程体系里边的笔记》的内核模块加载的笔记里边,提到了几个驱动相关的命令这里就不赘述了,但是有一个命令那篇笔记没写,这里就当补充一下吧。

1. 一个错误的解决

还记得前边使用buildroot构建根文件系统的时候,有一个报错:

image-20230806093054725

这里的这个目录起始就是为modprobe这个命令准备的,这个目录中将会存放驱动文件,然后可以不进入此目录,就直接使用modprobe命令加载指定的驱动。

“/lib/modules”这个目录是通用的,不管用的什么板子、什么内核,这部分是一样的。不一样的是这个目录下的子目录,会有一个以内核版本命名的目录,这个目录才是最终存放驱动的目录,例如“/lib/modules/4.1.15”,这里要根据我们所使用的 Linux 内核版本来设置,比如 ALPHA 开发板现在用的是 4.1.15 版本的 Linux 内核,因此就是“/lib/modules/4.1.15”。如果使用的其他版本内核,比如 5.14.31,那么就应该创建“/lib/modules/5.14.31”目录,否则 modprobe 命令无法加载驱动模块。

所以我们先自行创建这个目录,这个目录名怎么确定?我们可以看开机打印信息:

image-20230806093659410

然后再重启开发板:

1
mkdir -p /lib/modules/4.1.15-gfea85803-dirty

之后就会发现这个报错就会消失,但是又会报另一个错:

image-20230806093809304

可以看出, modprobe 提示无法打开“modules.dep”这个文件,因此驱动挂载失败了。我们不用手动创建 modules.dep 这个文件,直接输入 depmod 命令即可自动生成modules.dep,有些根文件系统可能没有 depmod 这个命令,如果没有这个命令就只能重新配置busybox了,素以我们可以进入buildroot源码中,执行以下命令打开busybox的配置窗口:

1
2
cd ~/5ALPHA/buildroot-2023.05.1/
sudo make busybox-menuconfig

然后就会打开busybox的配置窗口,我们勾选这个depmod,然后执行sudo make重新编译根文件系统,替换原来的根文件系统。

image-20230806094209209

最后重启,就会发现还在报,原来是还需要用这个命令自动生成一些文件,我们直接在终端执行depmod,就会生成下图这些文件:

image-20230806094650355

然后我们再重启,应该就不会有这些报错了:

2. 加载驱动

我们前边知道可以用insmod命令加载驱动,但是这个命令有一个缺点,就是驱动若是依赖其他驱动的话,就需要先加载其他依赖的驱动,然后这个驱动才能加载成功,这样是有些麻烦的,而且还需要指定驱动路径或者到驱动存放目录下才能加载。我们呢还有一个命令可以直接帮我们加载依赖的驱动并且不需要进去驱动所在目录,只是需要将驱动放在指定的目录下。就是下边的命令:

1
modprobe module_load.ko

然后会有以下信息:

image-20230806095412176

从图中可以看出,报错了,第一次并未加载成功,这个时候我们需要执行一次depmod命令重新生成一下这几个文件:

image-20230806095516857

重新生成后,就可以成功加载驱动啦。