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