前面几次操作,从编译环境到NFS共享目录全部搞定后,开始学习驱动开发,第一个helloworld驱动
一,驱动文件的关键要素:
一个最简单的LINUX驱动主要包含以下几个部分:
1,头文件
驱动需要包含内核相关的头文件,必须包含<linux/module.h>和<linux/init.h>
2,驱动加载函数
当加载驱动的时候,驱动加载函数会自动被内核执行
3,驱动卸载函数
当卸载驱动的时候,驱动卸载函数会自动被内核执行
4,许可证声明
LINUX内核是开源的,遵守GPL协议 ,驱动在加载 的时候也要遵守相关的协议 ,可以接收的LICENSE有“GPL”, “GPL V2", ”GPL and additional rights“,”dual BSD/GPL",内核中常见的GPL V2
5,模块参数(可选 )
模块参数是模块被加载的时候传递给内核模块的值
6,作者和版本信息(可选 )
可以声明驱动的作者和代码的版本信息
在/kernel/drivers/char/01_helloworld目录下新建一个helloworld.c文件
内容参照上面要求写成如下所示:
二,驱动的编译
1,编译方式有两种:
1)将驱动放到Linuxm内核里面,然后编译LINUX内核,将驱动编译到LINUX内核中
2)将驱动编译成内核模块,独立于LINUX内核外,内核模块是LINUX系统中一个特殊的机制,可以将一些使用频率很少或者暂时不用的功能编译成内核模块,在需要的时候动态加载到内核里。 使用内核模块可以减小内核的体积,加快启动速度,并且在系统运行的时候插入或者卸载驱动,无需重启系统,内核模块的后缀是.ko
三,编译成模块的方法:
注:要先把内核编译通过后才能进行驱动模块的编译。
1,在helloworld.c同目录下创建一个Makefile文件,格式如下:
export ARCH=arm64
export CROSS_COMPILE=/home/topeet/wnlinux/rk3568_linux_5.10/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-
obj-m+=helloworld.o
KDIR:=/home/topeet/wnlinux/rk3568_linux_5.10/kernel
PWD?=$(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
echo $(PWD)
clean:
make -C $(KDIR) M=$(PWD) clean
注:export ARCH和CROSS_COMPILE 设置交叉编译中环境变量的值
其中CROSS_COMPILE的值为编译开发板镜像文件交叉编译工具下的工具链,不要随意指定其他的
obj-m表示把目标文件helloworld.o作为模块进行编译
KDIR变量使用绝对路径方式指定内核源码的路径,这里的内核源码是编译生成开发板镜像文件的内核源码,不要搞错,否则可能编译出的KO文件版本和镜像版本不一致,导致insmod不成功
PWD变量获取Makefile文件所在的路径
make -C $(KDIR) M=$(PWD) modules,进到 KDIR目录,使用PWD路径下的源码和MAKEFILE文件编译驱动模块
编译出helloworld.ko文件
四,在开发板上装载模块
1,把生成的helloworld.ko文件复制到/home/nfs路径下
2,在开发板上的/mnt/路径下看到该文件
3,使用dmesg -C清除启动中的打印信息方便查看模块加载和卸载
至此,第一个helloworld驱动模块的编写,编译和装载,卸载完成 。
五,编译进内核
1,在helloworld.c同级目录下创建Kconfig文件,编写内容如下:
config helloworld
bool "helloworld driver support"
default y
help
this is the helloworld driver help info
2,在该目录的上一级目录下修改Kconfig文件,添加一行,使上一级的KCONFIG和新加的驱动的KCONFIG文件有关联
3,回到内核目录路径下,执行make menuconfig,在字符设备下可以看到如下信息
默认编译进内核,执行save,保存为.config文件。
3,在新加驱动的路径下添加makefile文件,原来的编译成模块的makefile文件被重命令为module_makefile放在该目录下
在新的makefile文件下添加如下内容:
obj-$(CONFIG_helloworld):=helloworld.o
在上一级char目录下修改makefile文件 ,添加如下所示
4,回到源码目录下,由于./build.sh kernel时编译的是ROCK的默认配置文件,会生成新的.config文件,没有helloworld驱动,把新编译的驱动给破坏,所以使用cp命令,把包含有helloworld驱动的.config文件复制为默认config文件
5,编译内核
./build.sh kernel, 在kernel目录下生成boot.img文件,拷贝到烧写工具目录下
6,往开发板上烧写
按着音量+键,然后再按电源键上电,上电后在虚拟机上烧写工具目录下执行命令
./upgrade_tool di -boot boot.img
烧写完成后重启开发板,使用命令dmesg | grep hello发现启动过程的打印
证明驱动已经编译进内核,启动成功。