Linux 驱动开发流程与框架简介

参考:正点原子I.MX6U嵌入式Linux驱动开发指南 V1.5.1

1 Linux驱动开发概述

1.1 学习驱动开发或软件开发的核心思想。

Linux驱动开发,像单片机裸机开发一样,直接操作寄存器模式已不现实。 Linux驱动开发,就是驱动框架的开发。甚至学习软件,就是学习框架。Linux 驱动开发或软件开发的学习方法:借鉴。

1.2 驱动三大类型

1、字符设备驱动(最常见);
2、块设备驱动(块设备就是储存设备,如ROM、RAM、emmc、flash等);
3、网络设备驱动。

1.3 Linux驱动开发和设备树的关系

驱动开发的第一件事就是在设备树文件中添加板子的各硬件设备信息。详细参考“设备树简介”文档。

1.4 Linux 驱动开发和应用开发

1、Linux应用程序跑在用户空间,简称用户态;Linux驱动程序跑在内核空间,简称内核态。内核态中有uboot、kernel和设备树文件(xxx.dtb)。
2、Linux 同时存在用户态和内核态的目的是提高LInux系统的安全性。
3、Linux应用程序不能直接访问内核资源,有三种方式可以使应用程序间接访问内核资源:系统调用、异常(中断)和陷入。

2 字符设备驱动框架

2.1 驱动开发概述

1、Linux下一切皆文件。无论是字符设备,还是块设备,甚至是网络设备,在Linux下都是文件。对设备(驱动)的操作,就是对文件的操作,也就是文件下open、close、read和write等函数的使用。
2、字符设备驱动的编写就是对file_operation结构体成员变量的实现。

2.2 Linux 驱动开发和运行方式

法一:将Linux驱动编译进内核。此方法一般用在驱动编写和测试通过,产品最终发布的情况下。
法二:将编辑好的驱动程序源码(xxx.c文件)通过Make命令(Makefile文件要自己编写)编译成驱动模块(xxx.ko文件),然后再Linux命令行下通过加载和卸载驱动模块,运行驱动。此方法一般是用在开发和测试驱动程序的情况下。

2.3 驱动模块的加载与卸载步骤

2.3.1 前提

编辑好驱动源码文件(xxx.c),通过Make命令,生成驱动模块(xxx.ko);打开Linux系统命令行。

2.3.2 驱动模块放置

将驱动模块(xxx.ko)移动到 /lib/modules/4.1.15文件夹下。若没有,新建此路径。

2.3.3 驱动模块加载

命令一:insmod xxx.ko;
命令二:modprobe xxx.ko。
insmod和modprobe的区别,modprobe命令能解决模块依赖关系,更加智能。

2.3.4 查看已加载的模块

命令:lsmod。

2.3.5 设备查看

命令:cat/lproc/devices
此命令查看当前系统中的所有设备,检查“2.3.3 步骤”是否将模块加载成功。

2.3.6 手动创建设备节点

命令:mknod /dev/chrdevbase c 200 0
c表示字符设备, 200 表示主设备号,0 表示此设备号。主次设备号要根据实际情况填写,

2.3.7 卸载模块

命令:rmmod

2.4 驱动程序/框架 开发详情。

2.4.1 操作环境

驱动源码文件,即xxx.c文件。

2.4.2 设备号

1、每一个硬件设备,在Linux系统内都对应一个设备号。
2、设备号的类型为dev_t,实际为32位无符号整形。
3、一个设备号分为主设备号和次设备号。主设备号占用32位字节的高12位,次设备号占用32位字节的低20位。
4、设备号相关操作函数
A、获取主设备号:MAJOR(dev_t);
B、获取次设备号:MINOR(dev_t);
C、主次设备号合成完整的设备号:dev_t=MKDEV(major,minor)。

2.4.3 设备的注册与注销

2.4.3.1 字符设备注册函数

1、注册函数:register_chrdev(主设备号,设备名称,file_opretions *fops)。
2、register_chrdev函数是众多注册函数中的一种,且是比较老的一种,现在已不常用。

2.4.3.2 字符设备注销函数

1、注销函数:unregister_chrdev(主设备号,设备名字)。
2、unregister_chrdev函数和register_chrdev函数对应,是众多注销函数中的一种,且是比较老的一种,现在已不常用。

2.4.4 file_operations结构体

在驱动开发中,file_operations结构体非常重要。其下成员和若干函数关联。通过和file_operations结构体成员关联的open、close、read和write等函数,可实现对硬件设备(其实是文件,因为Linux下一切皆文件)的操作。
file_operations结构体是设备驱动程序实现目标任务所在。

2.4.5 补充:设备的注册与注销-新函数

2.4.5.1 设备注册register_chrdev与注销函数unregister_chrdev的缺点

1、只能指定主设备号,不能指定次设备号。指定主设备号号,其下的所有次设备号都被占用,浪费了次设备号。
2、需要事先查询当前Linux系统中那些主设备号没有被占用,然后才能手动指定使用那些“闲置”的主设备号。
3、将驱动模块加载成功后,还需要手动使用mknod命令创建设备节点,不能自动创建设备节点文件。

2.4.5.2 设备号申请/指定与释放函数

1、向Linux系统申请一个未知的且未被占用的设备号函数
函数原型:int alloc_chrdev_region(dev_t * dev,unsigned baseminor,unsigned count,const char * name)
参数解析:alloc_chrdev_region(设备号-接受Linux系统分配的设备号,次设备号起始值,次设备号数量,设备名称)。
2、向Linux系统指定一个已知的未被占用的设备号函数
函数原型:int register_chrdev_fegion(dev_t from,unsigned count,const char * name)
参数解析:alloc_chrdev_region(要指定的设备号,要指定的设备号数量,设备名称)
3、设备号释放函数
函数原型: void unregister_chrdev_region(dev_t from,unsigned count)
参数解析:unregister_chrdev_region(要释放的设备号,要释放的设备号数量)。
用unregister_chrdev_region函数申请的设备号和unregister_chrdev_region函数指定的设备号,都可以用unregister_chrdev_region函数释放。

2.4.5.3 字符设备注册和注销-新函数

1、用cdev结构体描述字符设备
2、用 viod cdev_init (struct cdev * cdev, const struct file_operations * fops)函数初始化cdev结构体。
注意:file_operations结构体出现,参考2.4.4 。
3、用 int cdev_add(struct cdev * p,dev_t dev,unsigned count)函数向Linux 内核添加字符设备。
4、用void cdev_del (struct cdev * p)函数删除字符设备。

2.4.5.4 实现自动创建设备节点(参见2.3.6)

1、原理:udev/mdev机制
2、创建类:struct class * class_create(struct module * owner,const char * name)
3、删除类(卸载驱动时):void class_destroy (struct class * cls)
4、创建设备:struct device *device_create(struct class *class,struct device *parent,dev_t devt,void *drvdata,const char *fmt, …)
5、删除设备(卸载驱动时):void device_destroy(struct class *class, dev_t devt)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值