由于嵌入式系统分层,应用层要想操作硬件需通过内核层。驱动对上提供系统调用函数,对下封装了对底层硬件的一些基本操作。笔者目前不了解驱动程序的编辑,所以本章是在已经有驱动程序(fs4412_led_drv.c)和对应的应用程序(fs4412_led_app.c),来实现黑盒子移植(不去理解驱动程序的细节),实现控制led灯的闪烁。
通过驱动模块的方式,每次运行应用程序前手动加载模块,减少内核的开支。
1.添加驱动程序到内核源码的一个路径
root@linux:~# cp fs4412_led_drv.c /root/linux-4.19.1/drivers/char
2.配置同级目录下的Kconfig 和 Makefile文件
Kconfig
config FS4412_LED
tristate "FS4412 LED Driver Support"
depends on ARCH_EXYNOS4
help
support led device on FS4412 develop board
Makefile
obj-$(CONFIG_FS4412_LED) += fs4412_led_drv.o
3.make menuconfig 进行内核选配,把刚刚指定的驱动指定为模块方式添加(M)
4.到内核根目录,make modules 生成模块
5.make uImage 编译内核,将驱动编译生成的模块移动到nfs跟文件系统下
root@linux:~/linux-4.19.1/drivers/char# cp fs4412_led_drv.ko /nfs/rootfs
6.把内核覆盖到 tftp跟目录下
cp arch/arm/boot/uImage /tftpboot/
7.编译应用程序,并将应用程序移动到nfs跟文件系统下
root@linux:~# arm-none-linux-gnueabi-gcc fs4412_led_app.c
root@linux:~# cp a.out /nfs/rootfs
板子上电,运行内核,挂载成功nfs后,串口输入
[root@farsight ]# ls
[root@farsight ]# insmod fs4412_led_drv.ko
[root@farsight ]# mknod /dev/led c 500 0
[root@farsight ]# ./a.out
ps:insmod 加载模块;mknod 关联设备。500是主设备号 0此设备号,在驱动程序里可以找到;a.out 可执行文件。
为了方便,也可以把编译驱动,这个部分剥离出去。使用下面的Makefile文件编译
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /root/linux-4.19.1
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules* a.out
else
obj-m := fs4412_led_drv.o
endif
ps:KERNELDIR ?= /root/linux-4.19.1 ,指定内核的路径,这里借用内核根目录的Makefile文件进行编译;
obj-m := fs4412_led_drv.o ,fs4412_led_drv.o是指定目标文件
make 之后,将生成的fs4412_led_drv.o文件添加到内核源码,驱动模块 fs4412_led_drv.ko添加到nfs跟目录。