Linux驱动开发
一、驱动分类
Linux中包含三大类驱动:字符设备驱动、块设备驱动和网络设备驱动。其中字符设备驱动是最大的一类驱动,因为字符设备最多,从led到I2C、SPI、音频等都属于字符设备驱动。块设备驱动和网络设备驱动都要比字符设备驱动复杂。因为其比较复杂,所以半导体厂商都已经帮我们写好了,大部分情况下都是可以直接使用的。所谓的块设备驱动就是存储器设备的驱动,比如EMMC、NAND、SD卡和U盘等存储设备
二、字符设备驱动开发
字符设备驱动是Linux驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的。我们先来了解Linux下的应用程序是如何调用驱动程序的,如下图:

应用程序运行在用户空间,而Linux驱动属于内核的一部分,因此驱动运行于内核空间。open、close、write和read等这些函数是由C库提供的,在LInux系统中,系统调用作为C库的一部分。

三、Linux设备号
1、设备好的组成
为了方便管理,Linux中每个设备都有一个设备号,设备号由主设备号和次设备号两部分组成,主设备号表示某一个具体的驱动,次设备号表示使用这个驱动的各个设备。Linux提供了一个名为dev_t的数据类型表示设备号,dev_t定义在include/linux/types.h里面。dev_t其实是unsigned int类型,是一个32位的数据类型。其中高12位是主设备号,低20位是次设备号,因此Linux系统中主设备号范围是0~4095
设备号的操作函数
MAJOR用于从dev_t中获取主设备号,将dev_t右移20位即可
MINOR用于从dev_t中获取次设备号,取dev_t的低20位即可
MKDEV用于将给定的主设备号和次设备号的值组合成dev_t类型的设备号
2、设备号的分配
静态设备号:注册字符设备需要给设备指定一个设备号,这个设备号可以是驱动开发者静态指定的设备号,但是要注意该设备号没有被内核开发者分配掉。使用cat/proc/devices命令即可查看当前系统中已经使用的设备号
使用register_chrdev函数注册字符设备的时候只需要给定一个主设备号即可
/* 注册字符设备驱动 */
retvalue = register_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME, &chrdevbase_fops);
这是老版本字符设备注册函数,其0~1048575(2^20-1)这个区间的次设备号全部设置为0
动态分配设备号:使用设备号的时候向linux内核申请,需要几个就申请几个,由linux内核分配设备可以使用的设备号。在注册字符设备之前先申请一个设备号,系统会自动给你一个没有被使用的设备号,这样就避免了冲突,卸载驱动的时候释放掉这个设备号即可
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
dev:保存申请到的设备号
baseminor:次设备号起始地址,alloc_chrdev_region可以申请一段连续的多个设备号,这些设备好的主设备号一样,但是次设备号不同,次设备号以baseminor为起始地址开始递增。一般baseminor为0,也就是次设备号从0开始
count:要申请的设备号数量
name:设别名字
如果给定了设备的主设备号和次设备号就使用如下所示函数来注册设备号
int register_chrdev_region(dev_t from, unsigned count, const char *name)
参数 from 是要申请的起始设备号,也就是给定的设备号
参数 count 是要申请的数量,一般都是一个
参数 name 是设备名字
一般采用动态分配设备号,模板如下
/* 注册字符设备驱动 */
/* 1、创建设备号 */
if (newchrled.major)
{ /* 定义了设备号 */newchrled.devid = MKDEV(newchrled.major, 0);register_chrdev_region(newchrled.devid, NEWCHRLED_CNT, NEWCHRLED_NAME);
}
else
{ /* 没有定义设备号 */alloc_chrdev_region(&newchrled.devid, 0, NEWCHRLED_CNT, NEWCHRLED_NAME); /* 申请设备号 */newchrled.major = MAJOR(newchrled.devid); /* 获取分配号的主设备号 */newchrled.minor = MINOR(newchrled.devid); /* 获取分配号的次设备号 */
}
printk("newcheled major=%d,minor=%d\r\n",newchrled.major, newchrled.minor);
注销设备号
void unregister_chrdev_region(dev_t from, unsigned count)
四、模块注册与卸载
Linux驱动有两种运行方式,第一种是将驱动编译进Linux内核中,当Linux内核启动的时候就会自动运行驱动程序。第二种是将驱动编写成模块(Linux下模块扩展名为ko),在Linux内核启动以后使用相应命令加载驱动模块
模块有加载和卸载两种操作,模块的加载和卸载注册函数如下
module_init(xxx_init); //注册模块加载函数
module_exit(xxx_exit); //注册模块卸载函数
module_init函数来向Linux内核注册一个模块加载函数,参数xxx_init就是需要注册的具体函数,当使用insmod命令加载驱动的时候,xxx_init这个函数就会被调用
module_exit函数用来向Linux内核注册一个模块卸载函数,参数xxx_exit就是需要注册的函数,当使用rmmod命令卸载驱动的时候xxx_exit就会被调用
五、字符设备注册与注销
当驱动模块加载成功需要注册字符设备,卸载驱动模块的时候也需要注销掉字符设备
static inline int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)
static inline void unregister_chrdev(unsigned int major, const char *name)
register_chrdev函数用于注册字符设备,unregister_chrdev注销掉字符设备
一般字符设备的注册在驱动模块的入口函数xxx_init中进行,字符设备的注销在驱动模块的出口函数xxx_exit进行
六、LICENSE和作者信息
在驱动中加如LICENSE和作者信息,其中LICENSE是必须添加的,否则的话编译会报错,作者信息可以不添加
MODULE_LICENSE("GPL") //添加模块 LICENSE 信息 ,LICENSE 采用 GPL 协议
MODULE_AUTHOR("mingfei") //添加模块作者信息
七、测试指令
1、加载驱动模块
驱动模块一般挂载在lib/modules/4.1.15目录下,所以需要编写的驱动模块和测试软件复制到根文件系统rootfs/lib/modules/4.1.15目录下,通过tftfp和nfs启动后,在开发板的lib/modules/4.1.15目录下存在驱动模块和测试软件
驱动编译完成以后扩展名是.ko,有两种命令可以加载模块:insmod和modprobe
加载驱动模块
insmod xxx.ko
modprobe xxx.ko
insmod不能解决模块的依赖关系,比如drv.ko依赖first.ko这个模块,就必须先使用insmod命令加载first.ko这个模块,然后再加载drv.ko这个模块
但是modprobe就不会存在这样的问题,modprobe会分析模块的依赖关系,然后会将所有的依赖模块都加载到内核中
若modprobe提示无法打开modules.dep,驱动挂载失败,输入depmod即可自动生成modules.dep
2、创建设备节点文件
驱动加载成功需要在/dev目录下创建一个与之对应设备节点文件,应用程序就是通过操作设备节点文件来完成对具体设备的操作
创建/dev/chrdev设备节点文件
mknod /dev/chrdev c 200 0
mknod:创建节点命令
/dev/chrdev:要创建的节点文件
c:字符设备
200 0:设备的主设备号和次设备号
创建完成以后就会存在/dev/chrdev文件,可以使用ls/dev/chrdev -l命令查看
3、设备测试
运行测试程序
./xxx(程序) 参数1 参数2... (参数传给应用层的main函数)
./chrdevbaseApp /dev/chrdevbase 1 //例如测试对chrdevbase设备的写操作
4、卸载驱动模块
rmmod xxx.ko
卸载后可以使用lsmod查看卸载模块是否成功
相关文章:

Linux驱动开发
一、驱动分类Linux中包含三大类驱动:字符设备驱动、块设备驱动和网络设备驱动。其中字符设备驱动是最大的一类驱动,因为字符设备最多,从led到I2C、SPI、音频等都属于字符设备驱动。块设备驱动和网络设备驱动都要比字符设备驱动复杂。因为其比…...
32--Vue-前端开发-Vue语法之组件化开发
一、vue语法回顾 购物车的例子 eg1:计算商品价格(掌握对象的迭代方法) <!DOCTYPE html> <html lang="en"> <head>...

打怪升级之CFileDialog类介绍
CFileDialog类 CFileDialog封装用于文件打开操作或文件保存操作的常见对话框。信息来源自Windows官方文档:https://learn.microsoft.com/zh-cn/cpp/mfc/reference/cfiledialog-class?viewmsvc-170 这里重点介绍几个常用的函数功能: 构造函数 explic…...

配天智造自主原创数字工厂:百余名员工人均创收122万
配天智造(832223)2022年度报告显示,报告期内公司实现营业收入1.3亿元,同比增长52%,归属于挂牌公司股东的净利润3867万元,同比增长28.11%。而这家公司全部在职员工仅有107人,人均创收约为122万。…...

COLMAP
简介:在使用instant-ngp过程中需要使用COLMAP得到模型的必要输入,比如模型需要的相机外参我们就可以通过COLMAP中的sparse reconstruction稀疏重建得到;而对于depth map深度图我们则需要dense reconstruction稠密重建得到,下面我们…...
2023-3-8 刷题情况
礼盒的最大甜蜜度 题目描述 给你一个正整数数组 price ,其中 price[i] 表示第 i 类糖果的价格,另给你一个正整数 k 。 商店组合 k 类 不同 糖果打包成礼盒出售。礼盒的 甜蜜度 是礼盒中任意两种糖果 价格 绝对差的最小值。 返回礼盒的 最大 甜蜜度。…...
关于长连接服务器和客户端之间要加入心跳的一些讨论
在之前的章节里深入浅出TCPIP之深入浅出TCPIP之TCP重传机制 我们都知道了TCPIP协议栈有个默认的TCP心跳机制,这个心跳机制是和socket绑定的,可以对指定的套接字开启协议栈的心跳检测机制。默认情况下,协议栈的心跳机制对socket套接字是关闭的,如果要使用需要人为开启的。 比…...

LeetCode——1590. 使数组和能被 P 整除
一、题目 给你一个正整数数组 nums,请你移除 最短 子数组(可以为 空),使得剩余元素的 和 能被 p 整除。 不允许 将整个数组都移除。 请你返回你需要移除的最短子数组的长度,如果无法满足题目要求,返回 -1…...

12N65-ASEMI高压MOS管12N65
编辑-Z 12N65在TO-220封装里的静态漏极源导通电阻(RDS(ON))为0.68Ω,是一款N沟道高压MOS管。12N65的最大脉冲正向电流ISM为48A,零栅极电压漏极电流(IDSS)为10uA,其工作时耐温度范围为-55~150摄氏度。12N65功耗&#x…...

cushy-serial 一个轻量级Python serial库
本文自笔者博客: https://www.blog.zeeland.cn/archives/rgoihgxcoci3 简介 cushy-serial是一个轻量级的Serial框架,初衷是希望使Serial编程变得更加简单、快捷,因此,相较于传统的pyserial,该框架可以更加快速地构建起一个serial…...
音视频开发系列(7)——Opengl常用Api介绍part1
GLES20.glTexParameteri GLES20.glTexParameteri是OpenGL ES 2.0用于设置纹理过滤器和纹理包装模式的函数。它有三个参数: target参数 target参数指定要设置纹理参数的纹理目标,根据不同的target值,glTexParameteri函数的行为也会有所不同…...

linux时间的特殊用法
今天介绍linux下Date时间命令相关的特殊用法 date (当前的时间) 修改系统当前时间: date -s "2022-6-20 9:33:50" 昨天的时间是我们比较常用的: date -d "yesterday" %Y%m%d ( 昨天的时间) date -d "1 day ago" %Y%m%d …...
axios 封装,API接口统一管理
分享一个自己封装的 axios 网络请求 主要的功能及其优点: 将所有的接口放在一个文件夹中管理(api.js)。并且可以支持动态接口,就是 api.js 文件中定义的接口可以使用 :xx 占位,根据需要动态的改变。动态接口用法模仿…...

SpringBoot使用Redis实现缓存
目录 实现步骤 1. 在 pom.xml 配置文件中添加如下依赖 2. 在 application.properties 中添加如下配置 3. 新建 RedisConfig.class,继承 CachingConfigurerSupport,添加如下方法 4. 新建 RedisService.class 添加如下方法 注意:cacheKey…...
[失业前端恶补算法]JavaScript leetcode刷题top100(三)
专栏声明:只求用最简单的,容易理解的方法通过,不求优化,不喜勿喷 今天更新五个 easy 难度题目: 相交链表 题面 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个…...

Spark RDD的设计与运行原理
一、Spark RDD概念 一个RDD就是一个分布式对象集合,本质上是一个只读的分区记录集合,每个RDD可以分成多个分区,每个分区就是一个数据集片段,并且一个RDD的不同分区可以被保存到集群中不同的节点上,从而可以在集群中的…...

Golang的下载与安装
Windows系统 进入golang官方下载网站:所有版本 - Go 编程语言如图所示 下载后打开您下载的 MSI 文件,然后按照提示安装 Go。 验证是否已安装 Go。...

广州蓝景分享—8大Web前端开发的趋势
2023 年 1 月 11 日,2022 年度 StateOfJS 调查结果正式公布!StateOfJS 是前端生态圈中比较有影响力的且规模较大的数据调查。本文就来解读一下 2022 年 StateOfJS 的调查结果! JavaScript 发展很快,但似乎 JavaScript 开发人员的…...

Java学习-MySQL-创建数据库表
Java学习-MySQL-创建数据库表 SHOW DATABASESUSE school CREATE TABLE IF NOT EXISTS student( id INT(10) NOT NULL AUTO_INCREMENT COMMENT 学号, name VARCHAR(30) NOT NULL DEFAULT 匿名 COMMENT 姓名, pws VARCHAR(20) NOT NULL DEFAULT 123456 COMMENT 密码, sex VARCHA…...

Ethercat学习-GD32以太网学习
文章目录1、GD32F4以太网简介2、以太网模框图简介3、以太网主要模块介绍SMI接口RMII接口与MII接口DMA控制器4、以太网配置流程5、其他1、GD32F4以太网简介 GD32F4系列以太网模块包含10/100Mbps以太网MAC,数据的收发都通过DMA进行操作,支持MII࿰…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...