make -j6 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
mkimage -A arm -O linux -T kernel -C none -a 0x41000000 -e 0x41000040 -n "aaa" -d zImage uImage
观察现象
linux@ubuntu:~/Level10/day6/linux-5.4.79$ make -j6 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
CALL scripts/atomic/check-atomics.sh
CALL scripts/checksyscalls.sh
CHK include/generated/compile.h
CC drivers/char/fs4412_led_drv.o //发现已经被编译进去
drivers/char/fs4412_led_drv.c:81:8: warning: return type defaults to 'int' [-Wreturn-type]
AR drivers/char/built-in.a
AR drivers/built-in.a
GEN .version
CHK include/generated/compile.h
UPD include/generated/compile.h
CC init/version.o
AR init/built-in.a
LD vmlinux.o
MODPOST vmlinux.o
WARNING: "return_address" [vmlinux] is a static EXPORT_SYMBOL_GPL
MODINFO modules.builtin.modinfo
LD .tmp_vmlinux.kallsyms1
KSYM .tmp_vmlinux.kallsyms1.o
LD .tmp_vmlinux.kallsyms2
KSYM .tmp_vmlinux.kallsyms2.o
LD vmlinux
SORTEX vmlinux
SYSMAP System.map
Building modules, stage 2.
MODPOST 105 modules
OBJCOPY arch/arm/boot/Image
Kernel: arch/arm/boot/Image is ready
GZIP arch/arm/boot/compressed/piggy_data
AS arch/arm/boot/compressed/piggy.o
LD arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
arm-none-linux-gnueabi-cc fs4412_led_app.c
mknod /dev/led c 501 0
[root@farsight ]# ./a.out
[ 301.024579] led_open
[ 301.025926] led on ..
open led ok
[ 301.127968] led off ..
[ 301.228970] led on ..
[ 301.329883] led off ..
[ 301.430882] led on ..
[ 301.531795] led off ..
[ 301.632796] led on ..
[ 301.733709] led off ..
[ 301.834709] led on ..
[ 301.935623] led off ..
灯闪烁,运行正常。
一般来讲每个文件夹下 都会有一个Makefile 对应一个Kconfig,二者之间必须联动,才能取得想要的效果。
修改 drivers/char/Kconfig,
执行命令 ,观察效果
linux@ubuntu:~/Level10/day6/linux-5.4.79$ make menuconfig
发现找到了刚添加进去的led选项,但现在更改此选项内核也不会发生改变,因为没有和Makefile形成联动
修改 drivers/char/Makefile
重新编译uImage,观察效果
[root@farsight ]# mknod /dev/led c 501 0
[root@farsight ]# ./a.out
open: No such device or address
取消led选中过后,再次执行,发现led的驱动的确没有编译进内核。
linux@ubuntu:~/develop/led$ make -j6 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
linux@ubuntu:~/develop/led$ ls
fs4412_led_drv.c fs4412_led_drv.ko fs4412_led_drv.mod fs4412_led_drv.mod.c
fs4412_led_drv.mod.o fs4412_led_drv.o Makefile modules.order Module.symvers
linux@ubuntu:~/develop/led$
fs4412_led_drv.ko文件 就是要的模块文件
linux@ubuntu:~/Level10/day6/linux-5.4.79/drivers/char$ vim Kconfig
linux@ubuntu:~/Level10/day6/linux-5.4.79$ make modules -j6 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
生成.ko模块文件(本方式是驱动放在内核文件夹下的生成.ko文件的方法,也可用 1. 配置为模块方式 中的的形式生成.ko文件)
[root@farsight ]# insmod fs4412_led_drv.ko
[ 140.582962] fs4412_led_drv: loading out-of-tree module taints kernel.
[ 140.589011] Led init 5
[root@farsight ]# mknod /dev/led c 501 0
[root@farsight ]# ./a.out
黑盒移植
两种方式
1. 驱动编译进内核
选则源码目录
修改Makefile
修改Kconfig
2. 将驱动编译成独立的模块
配置为模块方式 通过修改Kconfig
使用make modules 编译为模块
装载模块 insmod xxx.ko
创建设备结点 mknod /dev/xxx c xx xx
运行测试驱动的应用程序
白盒移植
需要阅读阅读源码,熟悉驱动框架
1. 字符设备 2. 平台设备
字符设备框架
User Mode ||
\/
------------------------------------
System Call Interface
||
Kernel Mode \/
Virture File System(VFS)
| | |
Character Block Network
| | |
Device interface
||
\/
--------------------------------------
Hardware Physical Device (Hardware)
1.一切设备皆文件
对设备的操作的就是 对设备文件的 read write
2. open read write ioctl
3. 将设备进行编号 设备号(主次设备号组成)
字符设备驱动相关
1. 注册获取设备号
2. 初始化设备
3. 操作设备 file_operations -- open release read write ioctl...
4. 两个宏定义 module_init module_exit 两个命令 insmod rmmod
5. 注册设备号 register_chrdev_region
6. cdev_init 初始化字符设备
7. cdev_add 添加字符设备到系统
驱动是被动调用的,是被应用程序触发的
应用程序的 open 调用到驱动的file_operations 的 open
应用程序的 read 调用到驱动的file_operations 的 read
应用程序的 write 调用到驱动的file_operations 的 write
应用程序的 ioctl 调用到驱动的file_operations 的 ioctl
应用程序的 close 调用到驱动的file_operations 的 release
1. 寄存器的地址值是根据芯片手册 和原理图找到的
2. 对寄存器地址内容操作不能直接使用物理地址,需要ioremap
3. ioremap 将物理地址 映射到虚拟地址
4. platform 用于将硬件信息 和驱动代码做分离
5. 通过名字匹配,匹配成功执行 probe函数
6. 驱动通过 platform_get_resource 获取硬件设备资源
7. 作用 容易维护