当前位置: 首页 > news >正文

驱动基础开发

1、字符设备传统开发模板

字符设备驱动框架,首先我们需要去用module_init这个宏去修饰整个驱动的入口函数,用module_exit去修饰整个驱动的出口函数,然后还需要用MODULE_LICENSE用于声明模块的许可证类型。
在入口函数里面我们需要注册字符设备,使用register_chrdev()注册字符设备,使用class_create来注册区分一个类,在用device_create来为这个类创造一个设备节点,供我们在linux根目录下的dev目录下给应用层程序访问。在register_chrdev注册时最重要的是要提供字符设备的结构体file_operations,这个结构体启动了内核和应用层交互数据的功能。需要实现file_operations结构体的open,write,read,release函数,对应于应用层的open,write,read,close

#include "asm-generic/errno-base.h"
#include "asm-generic/gpio.h"
#include "asm/uaccess.h"
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>struct gpios
{int gpio;int irq;char *name;
};static gpois gpios_s[2]={{115,0,"sr51"},
};static int major=0; 
static struct class *cls=NULL;static ssize_t sr51_read(struct file *file, char __user *buf, size_t size, loff_t * loff)
{char ker_buf[2]={0};int err=0;err=copy_from_user(ker_buf, buf, 1);if(err){return -EINVAL;}ker_buf[1]=gpio_get_value(gpios_s[0].gpio);copy_to_user(buf, ker_buf,2)return 2;
}static int sr51_release(struct inode *node, struct file *file)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);printk("fd close\n");return 0;}static int sr51_open(struct inode *node, struct file *file)
{printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);return 0;
}ssize_t sr51_write(struct file *file, const char __user *buf , size_t size , loff_t * loff)
{printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);return 0;
}static struct file_operations sr51_driver={.owner=THIS_MODULE,.open=sr51_open,.write=sr51_write,.read=sr51_read,.release=sr51_release,
};static  int __init sr51_driver_init(void)
{int err;err=gpio_request(gpios_s[0].gpio, gpios[0].name);if (err < 0) {printk("can not request gpio %s %d\n", gpios_s[0].gpio, gpios[0].name);return -ENODEV;}gpio_direction_output(gpios[0].gpio, 1);major=register_chrdev(0, "sr51",&sr51_driver);cls=class_create(THIS_MODULE,"sr51_class");if(IS_ERR(cls)){printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major,"sr51");return PTR_ERR(cls);}device_create(&cls, NULL, MKDEV(major, 0), NULL, "sr51");return 0;
}static  void __exit sr51_driver_exit(void)
{device_destroy(cls, MKDEV(major, 0));unregister_chrdev(major,"sr51");class_destroy(cls);gpio_free(gpios_s[0].gpio);
}module_init(sr51_driver_init);
module_exit(sr51_driver_exit);
MODULE_LICENSE("GPL");

2、不使用register_chrdev的另外一类驱动的注册方法

register_chrdev其实是cdev封装好的一个函数,他其实也会调用cdev_init(),cdev_add(),
初始化设备号的另一种方法
1、int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name);

1、dev_t *dev
这个参数是一个指向 dev_t 类型的指针。dev_t 是一个在 <sys/types.h> 中定义的数据类型,用于表示设备号。在调用 alloc_chrdev_region() 函数时,你需要传递一个 dev_t 类型的变量的地址给这个函数。如果函数成功地为你的字符设备驱动程序分配了一个设备号,那么它会将这个设备号存储在 dev 指针所指向的变量中。
2、unsigned baseminor次设备号
3、unsigned count几个次设备号
4、const char *name设备名称
2、void cdev_init(struct cdev *cdev, const struct file_operations *fops);
cdev设备号
fops字符设备结构体
3、int cdev_add(struct cdev *p, dev_t num, unsigned int count);
struct cdev *p:指向已经初始化的cdev结构体的指针。
dev_t num:分配给这个字符设备的设备号。这通常是通过alloc_chrdev_region()函数获得的。
unsigned int count:通常设置为1,除非你的字符设备支持多个次设备号。

3、当下用的最多的驱动开发,设备树加platform总线模型

设备树的作用:用于描述硬件的具体的功能。像gpio控制器,ii2c控制器,io多路复用控制器,spi控制器,中断控制器gic都需要使用设备树去描述这个硬件。
platform总线模型:他是一个虚拟的总线模型,内核里面使用bus_type这个结构体来描述这个虚拟总线,这个虚拟中心又分为左边一部分和右边一部分,左边一部分使用platform_device来描述,这个结构体它可以由程序员编写,也可以直接使用设备树自动生成(目前使用的是这个),而右边是使用的是platform_driver这个是由当下的驱动程序员来编写的,虚拟总线的功能就是让这两个设备相匹配,如果匹配到了,那么驱动就会被加载进内核当中。
3.1他们是怎么匹配到,然后加载进入内核的详细过程

在这里插入图片描述
1、设备树通常在系统引导阶段由引导加载器(如U-Boot)从预定义的配置文件加载,并传递给内核,它包含了硬件的层次结构和属性(如内存地址、中断号和GPIO配置等)。
2、设备树中的节点会被映射到内核中的platform_device结构体实例。每个设备节点通常包含compatible属性,此属性用于标识设备类型和需要加载的驱动。(第一次会比对)
3、设备通过platform_device_register函数在内核中注册。这个过程会为设备创建一个platform_device实例,并将其添加到platform_bus_type所代表的总线上。
设备注册后,内核会使用platform_bus_type中的.match函数来查找和该设备兼容的驱动程序。
4、驱动程序使用platform_driver_register函数注册自己,并提供一个platform_driver结构体,其中包含驱动程序的名称、匹配表、以及回调函数,如.probe和.remove。
.match回调函数确定一个驱动程序是否适用于某个特定的设备,这通常是基于设备的compatible属性进行匹配的。
5、当设备和驱动成功匹配时,驱动的.probe函数被调用,这是驱动初始化设备的地方。例如,驱动可能会配置设备使用的GPIO引脚,设置初始状态,或注册更高层的服务(如输入设备或网络接口)。
4、设备树的使用
设备树的常见属性:
compatible:用于在驱动匹配时使用的匹配字符串。
#address-cells:常见于父节点中用于规定子节点使用多少字长来描述硬件的起始地址。
#size-cells:常见于父节点中用于规定子节点使用多少字长来描述硬件的地址长度。

/ {
#address-cells = <1>;
#size-cells = <1>;
memory {
reg = <0x80000000 0x20000000>;
};
};

status:表示这个设备的状态
在这里插入图片描述
reg 节点:的本意是 register,用来表示寄存器地址。
但是在设备树里,它可以用来描述一段空间。反正对于 ARM 系统,寄存器和
内存是统一编址的,即访问寄存器时用某块地址,访问内存时用某块地址,在访
问方法上没有区别
chosen 节点:可以通过设备树文件给内核传入一些参数。

相关文章:

驱动基础开发

1、字符设备传统开发模板 字符设备驱动框架&#xff0c;首先我们需要去用module_init这个宏去修饰整个驱动的入口函数&#xff0c;用module_exit去修饰整个驱动的出口函数&#xff0c;然后还需要用MODULE_LICENSE用于声明模块的许可证类型。 在入口函数里面我们需要注册字符设…...

从苹果AppStore看AI开发者生态

从苹果 App Store 看 AI 开发者生态 在人工智能迅速发展的今天&#xff0c;我们不禁要问&#xff1a;未来的 AI 开发者生态将会是什么样子&#xff1f;为了回答这个问题&#xff0c;我们不妨回顾一下移动互联网时代最成功的开发者生态之一——苹果的 App Store。 通过分析 App …...

【Python学习-UI界面】PyQt5 小部件1-Label

QLabel 对象可用作显示不可编辑的文本、图像或动态GIF影片的占位符。 它还可以用作其他小部件的助记键。 标签可以显示普通文本、超链接或富文本。 1、普通文本 直接双击输入即可 2、添加超链接 选中对应Label&#xff0c;右键选择多信息文本&#xff0c;添加链接&#xff0c…...

【Linux详解】进度条实现 Linux下git 的远程上传

&#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;Linux—登神长阶 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&#x1f3fd;留言 &#x1f60d;收藏 &#x1f49e; &#x1f49e; &#x1f49e; &#x1f680;前言 &#x…...

Android进阶之路 - res、raw、assets 资源解析、区别对比

那天遇到一个资源目录层级的问题&#xff0c;索性重新整理记录一下&#xff0c;希望能帮到如吾往昔之少年的你们&#xff0c;哈哈哈哈哈哈… 一脸茫然&#xff0c;越写越多&#xff0c;时间成本属实有点大&#xff0c;就当一起来基础扫盲吧 resdrawablemipmapvaluescolor asset…...

从数字化到数智化:消费零售企业如何实现门店数智化管理?

随着信息技术的飞速发展&#xff0c;数字化已成为企业转型的必经之路。然而&#xff0c;数字化本身并不是目的&#xff0c;而是通往数智化的桥梁。数智化&#xff0c;即数据智能化&#xff0c;是指企业通过数字化手段收集和分析数据&#xff0c;进而利用这些数据驱动决策和创新…...

Linux中ES的安装

文章目录 一、ES是什么1.1、ES概念介绍1.2、技术架构1.2.1、Lucene介绍 1.3、ES的工作原理1.4、ES的适用场景 二、安装前的配置2.1、创建普通用户2.2、调整文件描述符数量和虚拟内存2.3、设置shell会话的资源限制&#xff08;软限制和硬限制&#xff09;2.4、增加虚拟内存的设置…...

Redis远程字典服务器(5) —— hash类型详解

目录 一&#xff0c;hash基本情况 二&#xff0c;hash常用命令详解 2.1 hset&#xff0c;hget&#xff0c;hexists&#xff0c;hdel 2.2 hexists&#xff0c;hdel 2.3 hkeys&#xff0c;hvals 2.4 hgetall&#xff0c;hmget 2.5 hlen&#xff0c;hsetnx 2.6 hincrby&am…...

MySQL | 行锁——记录锁、间隙锁 、临键锁、插入意向锁

1、InnoDB中的行锁 行锁&#xff08;Row Lock&#xff09; 也称为记录锁&#xff0c;顾名思义&#xff0c;就是锁住某一行&#xff08;某条记录row&#xff09;。需要注意的是&#xff0c;MySQL服务器层并没有实现行锁机制&#xff0c;行级锁只在存储引擎层实现。 优点&#x…...

【网络编程】TCP通信基础模型实现

tcpSer.c #include <myhead.h> #define SER_IP "192.168.119.143" // 设置IP地址 #define SER_PORT 6666 // 设置端口号 int main(int argc, const char *argv[]) {// 1.创建socketint serfd socket(AF_INET, SOCK_STREAM, 0);// 参数1表示ipv4// 参数2表…...

css rem之2024

话题开始前 我们都知道1rem是等于html fontSize标签的字体大小的&#xff0c;我们主要用来做移动端网页设计稿等比例在手机上面的显示。 看到的问题 这个html fontsize的大小是通过js动态计算的&#xff0c;而这个js的运行时晚于html渲染的&#xff0c;所以会导致一个问题&am…...

python自动化笔记:pytest框架

目录 一、pytest介绍二、测试用例命名规则2.1、pytest命名规则2.2、python命名规范 三、pytest运行方式3.1、主函数方式3.2、命令行方式3.3、通过pytest.ini的配置文件运行&#xff08;常用&#xff09; 四、跳过测试用例4.1 无条件跳过4.2 有条件跳过 五、用例的前后置&#x…...

wpf 路径动画 举例

先&#xff0c;我们需要在XAML中定义一个Path&#xff0c;这个Path将定义动画的路线。然后&#xff0c;我们将使用DoubleAnimationUsingPath来沿着这个路径移动一个元素&#xff08;比如一个矩形&#xff09;。 <Window x:Class"WpfApp.MainWindow" xmlns"…...

【C++】classes and object 2.8 取地址及const取地址操作符重载

这两个默认成员函数一般不用重新定义 &#xff0c;编译器默认会生成。 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std; class Date { public:Date* operator&(){return this;}const Date* operator&()const{return this;} privat…...

milvus helm k8s开启监控

https://milvus.io/docs/monitor.md 文章写的很清晰 &#xff0c;我这边做一下个人补充&#xff0c;初版可能只是配置&#xff0c;具体的grafana 监控报表后期补一下。 架构如下&#xff1a; values.yaml 配置 enabled: true 改为true metrics:enabled: trueserviceMonitor:…...

牛奶饮用学习笔记

1. 常见牛奶类型 1.1 蒙牛-每日鲜语-0脂肪鲜牛奶 项目每100mL NRV%能量146kJ 能量计算 250 mL 146 kJ / 100 mL 365 kJ 250\text{mL}\times146\text{kJ}/100\text{mL} 365\text{kJ} 250mL146kJ/100mL365kJ 1.2 伊利-舒化-高钙型无乳糖牛奶 项目每100mL NRV%能量269kJ …...

php防止页面重复刷新或者重复提交

2.核心代码 显示的逻辑&#xff1a; //获取防止刷新的唯一标识符,start $intFlag substr(md5(time()),6); $strFlag BAOXIAOSS_.$my_user_id.$intFlag; $smarty->assign(check_is_agin_post, $strFlag); //获取防止刷新的唯一标识符,end注意&#xff1a;前端页面提交加入…...

Springboot3 配置sql打印到控制台

一、pom.xml <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId><version>3.1.2</version></dependency> 二、application.yml com.lingyang.system # log4j2配…...

深入理解 GO 语言并发

1. 使用并发 在深入了解 Go 如何处理并发之前,先查看并发的概念。在计算机发展的早期阶段,计算机系统只有一个处理器负责执行所有指令。由于这种体系结构,计算机程序被编写成以串行的方式运行,在这种方式下,程序按照预定义的顺序逐个指令地执行。 随着计算机程序变得越来越…...

leetcode39组合总和

题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限制重复被选…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...