arm驱动开发学习总结
一:什么是驱动
驱动程序:就是对底层硬件设备的操作进行封装,并向上层提供函数接口。
Linux将驱动设备分为三类:字符设备、块设备、网络设备。
-
字符设备:只能一个字节一个字节的读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后顺序进行。字符设备是面向流的设备。
-
如鼠标、键盘、串口、控制台、LED等。
-
块设备:块设备驱动是以固定大小长度来传送和转移资料,块设备能够随机,不需要按照顺序地访问固定大小的数据片;
-
块设备包括硬盘、磁盘、U盘和SD卡等。
-
网络设备:网络设备主要负责主机之间的数据交换。
-
蓝牙,WIFI,网卡等。
二:字符设备驱动
1.字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的。
2.因为,应用程序位于用户空间,驱动程序位于内核空间,用户空间不可以直接调用内核空间的函数。所以必须经过系统调用,应用程序才可以调用驱动程序的函数。
应用程序调用驱动程序过程:
1.应用程序:
2.应用程序里的open(),write(),read()函数将调用驱动程序里的接口里的函数。
如:应用程序里open()调用接口结led_open();
2.应用和驱动之间的数据交换
(1)copy_from_user,用来将数据从用户空间复制到内核空间
(2)copy_to_user,用来将数据从内核空间复制到用户空间
3. 驱动程序结构:
驱动代码必须有4部分:
//1、头文件
#include <linux/init.h>
#include <linux/module.h>//2、驱动入口函数的声明,在内核加载驱动时,执行哪个函数;在内核卸载驱动时,执行哪个函数
//声明:加载时的入口声明
module_init(hello_init);
//声明:卸载时的入口声明
module_exit(hello_exit);//3、加载函数、卸载函数的实现
//加载函数的实现:当内核加载驱动(内核执行这个驱动时,就会调用的函数)
static int __init hello_init(void)
{return 0;
}//卸载函数的实现:当内核卸载驱动(内核删除这个驱动时,就会调用的函数)
static void __exit hello_exit(void)
{return 0;
}
//4、协议选择GPL
MODULE_LICENSE("GPL");
4.makefile文件
KERNEL_PATH=/home/ubuntu/code/kernel/linux-3.14
obj-m += 1st_drv.o #把.c文件编译为.o文件
#编译为驱动程序 .ko 要借助 已经编译过的内核
all:
make modules -C $(KERNEL_PATH) M=$(shell pwd) #去执行kernel目录下的makefile
install:
cp *.ko /nfsdir/rootfs