• Linux内核驱动开发-字符设备驱动框架


    1前置条件

    (1)【linux】内核编译结束
    (2)【linux】目录配置跳转文件:
    
    • 1
    • 2

    在这里插入图片描述

    补充:配置的跳转文件只能在【linux】目录下使用,子目录无法使用
    
    • 1

    2驱动框架

    2.1编写驱动程序

    #include 
    #include 
    #include 
    #include 
    
    #define DEVICE_MAJOR 200
    #define DEVICE_NAME  "first_device"
    
    int first_driver_open(struct inode *node, struct file *fp)
    {
    	printk("first_driver_open\n");
    	return 0;
    }
    
    ssize_t first_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset)
    {
    	printk("first_driver_read\n");
    	return 0;
    }
    
    ssize_t first_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
    {
    	printk("first_driver_write\n");
    	return 0;
    }
    
    int first_driver_close(struct inode *node, struct file *fp)
    {
    	printk("first_driver_close\n");
    	return 0;
    }
    
    static struct file_operations fops = 
    {
    	.owner = THIS_MODULE,
    	.open = first_driver_open,
    	.read = first_driver_read,
    	.write = first_driver_write,
    	.release = first_driver_close
    };
    
    static int __init first_driver_init(void)
    {	
    	register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &fops);
    	printk("first_driver_init OK\n");
    	return 0;
    }
    
    static void __exit first_driver_exit(void)
    {	
    	unregister_chrdev(DEVICE_MAJOR, DEVICE_NAME);
    	printk("first_driver_exit OK\n");
    }
    
    
    module_init(first_driver_init);
    module_exit(first_driver_exit);
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("XXX");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    2.2 编译驱动程序

    2.2.1编译方式1

    【step1】:将编写完成的驱动程序放至【linux/drivers/char】目录下
    【cp ./file_name.c linux/drivers/char】
    【step2】:修改内核配置文件
    【vi linux/drivers/char/Kconfig】
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    【step3】:修改编译规则,添加工程文件
    【vim linux/drivers/char/Makefile】
    
    • 1
    • 2

    在这里插入图片描述

    在这里插入图片描述

    【step4】:菜单配置
    【make menuconfig】
    
    • 1
    • 2

    在这里插入图片描述

    在这里插入图片描述

    修改为模式
    
    • 1

    在这里插入图片描述
    附:3种模式讲解

    当然,也可以使用【help】选项查看相关信息
    
    • 1

    在这里插入图片描述
    在这里插入图片描述

    【step5】:调用编译命令,进行驱动程序的编译
    【make modules】	
    
    • 1
    • 2

    在这里插入图片描述

    至此,采用方式1编译完成。当然,也可以查看编译后文件是否存在:
    
    • 1

    在这里插入图片描述

    这是一个需要手动添加到操作系统的文件。
    
    • 1

    2.2.2编译方式2

    【step1】:创建一个文件夹:是linux目录下的任意目录
    【mkdir my_drivers】
    
    • 1
    • 2

    在这里插入图片描述

    【step2】:将驱动程序源码放入该目录
    
    • 1

    在这里插入图片描述

    【step3】:该目录下创建【Makefile】文件
    【vim Makefile】
    
    • 1
    • 2
    KERNELDIR := /home/linux/s3c2440/linux-2.6.32.2/
    CURRENT_PATH := $(shell pwd)
    obj-m := first_driver.o
    
    build: kernel_modules
    
    kernel_modules:
    	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
    
    clean:
    	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    【step4】:编译
    【make】
    
    • 1
    • 2

    在这里插入图片描述

    至此,采用方式2编译完成。当然,也可以查看编译后文件是否存在:
    
    • 1

    在这里插入图片描述

    这是一个需要手动添加到操作系统的文件。
    
    • 1

    2.3移植驱动程序

    (1)将编译产生的【filename.ko】文件移植到开发板
    【cp drivers/char/first_driver.ko ~/nfs/rootfs】
    
    • 1
    • 2

    在这里插入图片描述

    在开发板种可以看到文件移植成功:
    
    • 1

    在这里插入图片描述

    2.4加载驱动程序

    (1)加载被移植到开发板的【filename.ko】文件
    【insmod filename.ko】
    
    • 1
    • 2

    在这里插入图片描述

    补充:
    查看加载成功的驱动:
    	【lsmod】
    
    • 1
    • 2
    • 3

    2.5卸载驱动程序

    (1)卸载被移植到开发板的【filename.ko】文件
    	【rmmod filename】
    
    • 1
    • 2

    2.6创建设备文件

    2.6.1创建设备文件方式1

    手动创建设备文件
    【mknod[options] name type major minor】
    【options】:
    【name】:【/dev】下的设备文件名
    【type】:设备型号,【c】
    【major】:主设备号
    【minor】:子设备号
    eg:【mknod /dev/first_driver c 200 0】
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    设备创建完毕,可以使用【ls】命令查看是否成功创建设备文件。
    
    • 1

    在这里插入图片描述

    补充:
    应用程序就是以【name】为入口点来调用驱动程序的。
    【mknod ?】:查看命令帮助
    【cat /proc/devices/】:查看设备
    【ls /dev】:查看设备文件
    
    删除设备文件:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    2.7调用驱动程序

    【step1】:其实就是在开发板上编写一个应用程序(主要是指main函数)
    编写应用程序:打开设备文件->调用文件I/O(系统I/O)->
    
    • 1
    • 2
    #include
    #include
    #include
    #include
    #include
    
    int main(void)
    {
        int fd=0;
    
        fd=open("dev/first_device",O_RDWR);
        if(fd<0)
        {
            printf("opening is error\n");
            return -1;
        }
    
        while(1)
        {
            int n=123;
            read(fd,&n,4);
            sleep(1);
            write(fd,&n,4);
            sleep(1);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    【step2】:编译应用程序
    
    • 1

    在这里插入图片描述

    【step3】:关闭开发板原有的设备驱动程序
    通过菜单配置命令:【make menuconfig】
    将对应的驱动模块的模式【<>】改为图中所标记的模式。
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    2.8编译并移植内核文件

    【make uImage】
    
    • 1

    在这里插入图片描述

    编译完成之后,将产生的镜像文件移植到开发板:
    【cp arch/arm/boot/uImage ~/tftpboot/】
    
    • 1
    • 2

    在这里插入图片描述

    2.9运行操作系统内核

    接下来,将操作系统运行在开发板上:
    【tftp 0x30008000 uImage】
    【bootm 0x30008000】
    
    • 1
    • 2
    • 3

    2.10开发板文件配置

    当新的内核文件在开发板上成功运行之后,接下来需要对开发板上的一个文件进行配置:
    
    • 1

    在这里插入图片描述

    关闭led相关配置:
    
    • 1

    在这里插入图片描述

    补充:
    (1)【reboot】:该命令将重启开发板,让开发板回到初始状态,从运行内核文件之后的所有操作需要重新配置。
    
    • 1
    • 2

    在这里插入图片描述

    (2)通过配置环境变量可以让开发板上电以后自动运行操作系统并挂载根目录:
    【setenv bootcmd 'tftp 0x30008000; bootm 0x30008000'】
    注意:环境变量配置完成一定要进行保存操作!!!
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    (3)环境变量配置完成之后可以重启开发板:可以看到开发板将自动运行操作系统并挂载根文件系统。
    【reset】:重启开发板
    
    • 1
    • 2

    在这里插入图片描述

    3板载驱动程序示例

    路径:【linux-2.6.32.2/drivers/char/mini2440_hello_module.c 】

    #include 
    #include 
    
    
    static int __init mini2440_hello_module_init(void)
    {
        printk("Hello, Mini2440 module is installed !\n");
        return 0;
    }
    
    static void __exit mini2440_hello_module_cleanup(void)
    {
        printk("Good-bye, Mini2440 module was removed!\n");
    }
    
    module_init(mini2440_hello_module_init);
    module_exit(mini2440_hello_module_cleanup);
    MODULE_LICENSE("GPL");
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    苹果电脑系统如何读取移动硬盘数据?
    洛谷 P1106 删数问题
    基础算法--双指针算法
    python最优化算法实战---线性规划之内点法
    运营商认证API在Java、Python、PHP中的使用教程
    网课查题API接口(免费)
    JavaScript 68 JavaScript Browser BOM 68.7 JavaScript Timing 事件
    学习新语言方法总结(一)
    [Druid-1.2.11源码系列]-9-Druid销毁线程
    78基于matlab的BiLSTM分类算法,输出迭代曲线,测试集和训练集分类结果和混淆矩阵
  • 原文地址:https://blog.csdn.net/qq_63713157/article/details/137960792