【Linux驱动】platform 设备驱动分离(一)—— 驱动分层及相关API

以目前为止的逻辑,无论是获取设备属性信息,还是实现驱动逻辑,都是放在一个驱动模块中。在没有设备树的情况下,如果我们只需要修改设备信息(如寄存器地址),那么我们就需要重新编译整个驱动模块。

很显然,设备信息的变化不应该影响到驱动逻辑的正常运行,这就需要引入驱动分层的概念。

一、整体架构

驱动分层总体可以分为三层

  • 设备层:负责管理设备属性信息,包含了一些外设硬件信息,如寄存器地址、引脚配置信息等
  • 驱动层:负责驱使设备的正常运作,驱动程序借由总线传递控制信号、数据,进而来控制设备
  • 总线:驱动和设备信息的月老,负责设备和驱动程序之间的通信和数据交换

驱动程序要想驱使设备,需要先让驱动与设备匹配,匹配工作由总线负责。只有当左侧的设备与右侧的驱动程序建立联系以后,驱动程序才可以驱使设备。

        (1) 当我们向系统注册一个驱动,总线会在左侧查找是否存在与之匹配的设备;

        (2) 当我们向系统注册一个设备,总线会在右侧查找是否存在与之匹配的驱动;

二、总线

Linux 内核使用 bus_type 结构体来表示总线,而 platform 总线是 bus_type 的一个实例,定义在 drivers/base/platform.c ,该文件中同样也定义了驱动和设备是否匹配的检测方式。

方式一:of 类型的匹配

设备树中包含 compatible 属性,而驱动中也有一个 of_match_table 成员变量,这个可以看做是驱动中的 compatible 属性。匹配时会检查设备树的compatible属性和驱动的 of_match_table 变量是否包含相同条目,如果存在,说明此设备和驱动匹配。

方式二:ACPI 匹配

驱动程序中包含一系列自己兼容的设备描述符,该设备描述符包含设备类型、供应商ID、设备ID等属性。以此作为xx设备是否与驱动匹配的判断依据。

方式三:id_table 匹配

在Linux内核中使用 platform_driver 结构体来表示 platform 驱动,每个 platform_driver 结构体有一个 id_table 成员变量,保存了很多 id 信息。这些 id 信息存放着这个 platformd 驱动所支持的驱动类型。

方式四:name 字段匹配

直接比较驱动模块 platform_driver 中 device_driver 的 name 变量设备树中的 name 属性(或platform_device的name变量)

三、设备层

在Linux内核中使用 platform_device 结构体来表示 platform 设备,该设备可以是一个真实存在的设备,也可以只是一个虚拟的设备。platform_device 结构体定义在 linux/platform_device.h 文件中。

1、platform_device

这里主要初始化下面三个成员变量:

  • name:后续测试时使用第四种方式匹配,对此就需要用到 platform_device 的name变量
  • resource:资源数组,保存了寄存器相关信息(寄存器的起始、终止地址)
  • num_resources:resource 数组中资源的个数
struct platform_device {
	const char	*name;
	int		id;
	bool		id_auto;
	struct device	dev;
	u32		num_resources;
	struct resource	*resource;

	const struct platform_device_id	*id_entry;
	char *driver_override; /* Driver name to force a match */

	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;

	/* arch specific additions */
	struct pdev_archdata	archdata;
};

2、resource 

resource 结构体保存的是某个寄存器相关内容,resource 结构体的声明保存在 linux/ioport.h

struct resource {
	resource_size_t start;
	resource_size_t end;
	const char *name;
	unsigned long flags;
	struct resource *parent, *sibling, *child;
};
  • start:寄存器的起始地址
  • end:寄存器的终止地址
  • flags:表示资源类型,同样定义在 linux/ioport.h 

3、注册 platform 设备

platform 设备注册接口原型如下:

/**
 * @param pdev    要注册的platform设备
 * @return        成功返回 0 ,失败返回负值
 */
int platform_device_register(struct platform_device *pdev);

4、注销 platform 设备

platform 设备注销接口原型如下:

/**
 * @param drv     要注销的platform设备
 */
void platform_device_unregister(struct platform_device *pdev);

四、驱动层

在Linux内核中使用 platform_driver 结构体来表示 platform 驱动,该结构体定义在 linux/platform_device.h 文件中。

1、platform_driver

需要注意其中的 probe 函数和 remove 函数,当设备和驱动匹配成功,会调用probe函数;当 platform 驱动从内核中移除,会调用 remove 函数。

struct platform_driver {
	int (*probe)(struct platform_device *);
	int (*remove)(struct platform_device *);
	void (*shutdown)(struct platform_device *);
	int (*suspend)(struct platform_device *, pm_message_t state);
	int (*resume)(struct platform_device *);
	struct device_driver driver;
	const struct platform_device_id *id_table;
	bool prevent_deferred_probe;
};

2、device_driver

device_driver 保存与设备匹配时的相关驱动信息,在后续测试时使用第四种方式匹配,对此就需要用到 device_driver 结构体中的 name 变量

struct device_driver {
	const char		*name;            // platform 驱动名称
	struct bus_type		*bus;         // 总线类型

	struct module		*owner;
	const char		*mod_name;	/* used for built-in modules */

	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */

	const struct of_device_id	*of_match_table;
	const struct acpi_device_id	*acpi_match_table;

    // ...
}

3、注册 platform 驱动

platform 驱动注册接口原型如下(本质是宏):

/**
 * @param drv     要注册的platform驱动
 * @return        成功返回 0 ,失败返回负值
 */
int platform_driver_register(struct platform_driver *drv);

4、获取platform设备资源

platform_get_resource 可获取platform_device 中的 resource 数组,从上面可以了解到 resource 数组保存的是寄存器地址信息。

/**
 * @param pdev    要访问的platform设备
 * @param type    资源类型,对应resource结构体中的 flag 成员
 * @param index   访问resource数组的下标
 * @return        成功返回 resource 数组的首地址,失败返回0
 */
struct resource *platform_get_resource(struct platform_device * pdev,
					                   unsigned int type, 
                                       unsigned int index);

5、注销 platform 驱动

platform 驱动注销接口原型如下:

/**
 * @param drv     要注销的platform驱动
 */
void platform_driver_unregister(struct platform_driver *drv);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/314106.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

80V 72V 60V 48V 降12V 5V 3.3V 功耗低降压恒压芯片H6603

输入电压80V、72V、60V、48V:这些是电源系统中的不同电压水平,通常用于驱动各种设备。例如,电动汽车、电动自行车或工业设备中的电池系统可能以这些电压级别工作。 降12V:这可能是指一种电源模块,其功能是将输入电压&…

x-cmd pkg | dua - 磁盘使用分析器

目录 简介首次用户技术特点竞品和相关作品进一步阅读 简介 dua 是 Disk Usage Analyzer 的简写,该工具可以快速查看给定目录的磁盘空间使用情况。 对于想要深入了解磁盘空间使用情况并有效管理存储的用户来说,Dua 是一个很有价值的工具。通过使用 Dua …

自己动手造一个状态机

自己动手造一个状态机 引言有限自动状态机 (FSM)五要素应用场景优势 开源产品造个轮子改造点Looplab fsm示例演示实现解析 改造过程 引言 有限自动状态机 (Finite-state machine , FSM) 通常用来描述某个具有有限个状态的对象,并且在对象的生命周期中组成了一个状态…

Android 13 辅助屏导航栏不显示问题

问题 在Android 13 上开启辅助屏幕。但是发现辅助屏systemui 导航按 icon没有显示,但是点击对应的区域有作用 分析 可以用 anroid device monitor 工具分析视图 解决 public NavigationBarView(Context context, AttributeSet attrs) {super(context, attrs);//add star…

x-cmd pkg | smartctl - 用于监测和分析硬盘的工具

目录 简介首次用户功能特点竞品和相关作品进一步阅读 简介 smartctl 是一个用于监测和分析硬盘中 S.M.A.R.T.(自我检测,分析和报告技术)信息的命令行工具,是 Smartmontools 的一部分。通过 smartctl 工具,可以分析各种…

安泰电子前置微小信号放大器怎么用的

前置微小信号放大器是一种重要的电子设备,用于放大微弱的输入信号,提高系统的灵敏度。它在各种领域中都有广泛的应用,包括音频、通信、测量等。在这篇文章中,我们将详细介绍前置微小信号放大器的使用方法,以便更好地理…

Cdd诊断数据控中的zz rc yy

如上图所示的Cdd Candela Diagnostic Descriptions 诊断数据库会话定义中有许多的标识符缩写,如zz rc LL xx 等 其实这些字母没有意义,它们只是唯一地标识对话框中的组合组件。

HDFS概述

文章目录 HDFS背景定义HDFS 优缺点HDFS 组成HDFS文件块大小 HDFS背景定义 背景 先给大家介绍一下什么叫HDFS,我们生活在信息爆炸的时代,随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁…

国内镜像源配置方法(包括临时和永久方法)

国内镜像源: 阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/豆瓣 http://pypi.douban.com/simplePython官方 https://pypi.python.org/simple/v2ex http://pypi.v2ex.com/simple/中国科学院 http://pypi.mi…

【IDEA--dubug相关】-- 1. 取消debug的所有断点 2. debug侧边栏消失问题

下面是一些经常在日常debug时用到的场景,方便查看、与君共勉! 文章目录 1. 如何取消所有断点2. debug底部左边侧边栏消失 1. 如何取消所有断点 如图我们可能在项目中给很多代码行添加了断点,一个一个点取消麻烦 在debug运行中点击选中底部…

React Native 桥接组件封装原生组件属性

自定义属性可以让组件具备更多的灵活性,所以有必要在JS 层通过自定义属性动态传值。 一、添加原生组件属性 因为 ViewManager 管理了整个组件的行为,所以要新增组件属性也需要在这里面(如 InfoViewManager)进行定义。 1、在Inf…

[JVM] Java类的加载过程

Java类的加载过程 在Java中,类的加载是指在程序运行时将类的二进制数据加载到内存中,并转化为可以被JVM执行的形式的过程。类的加载过程主要包括以下几个步骤: 加载(Loading):通过类的全限定名,…

【Docker】数据管理之数据卷的挂载

一、什么是数据卷 为了很好的实现数据保存和数据共享,Docker提出了Volume这个概念,简单的说就是绕过默认的联合 文件系统,而以正常的文件或者目录的形式存在于宿主机上。又被称作数据卷。数据卷提供了一些有用的特性: 数据卷可以在…

Casper Network (CSPR)2024 年愿景:通过投资促进增长

Casper Network (CSPR)是行业领先的 Layer-1 区块链网络之一,通过推出了一系列值得关注的技术改进和倡议,已经为 2024 年做好了准备。 在过去的一年里,Casper Network (CSPR)不断取得里程碑式的进展,例如推…

设计模式—行为型模式之状态模式

设计模式—行为型模式之状态模式 状态(State)模式:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。 状态模式包含以下主要角色: 环境类&am…

构建基于RHEL9系列(CentOS9,AlmaLinux9,RockyLinux9等)的Nginx1.24.0的RPM包

本文适用:rhel9系列,或同类系统(CentOS9,AlmaLinux9,RockyLinux9等) 文档形成时期:2023年 因系统版本不同,构建部署应略有差异,但本文未做细分,对稍有经验者应不存在明显障碍。 因软件世界之复杂和个人能力…

使用主题模型和古老的人类推理进行无监督文本分类

一、说明 我在日常工作中不断遇到的一项挑战是在无法访问黄金标准标签的情况下标记文本数据。这绝不是一项微不足道的任务,在本文中,我将向您展示一种相对准确地完成此任务的方法,同时保持管道的可解释性和易于调整。 一些读者可能已经开始考…

x-cmd pkg | trash-cli - 类 Unix 系统的命令行垃圾桶

目录 简介首次用户技术特点竞品和相关作品进一步阅读 简介 trash-cli 是类 Unix 系统的命令行垃圾桶,用于移动文件到回收站,同时会记录文件的原地址和删除日期。 该工具使用与 GNOME、KDE ​​和 XFCE 等桌面环境相同的垃圾桶,所以即使是非 …

使用Web自动化测试工具显著好处

随着互联网技术的飞速发展,Web应用程序在企业中的重要性不断上升。为了确保Web应用程序的质量和稳定性,许多企业转向了Web自动化测试工具。下面是使用Web自动化测试工具的一些显著好处: 1. 提高测试覆盖率 Web自动化测试工具可以模拟用户与We…

网络中的网络 NiN

目录 1.NiN 2.代码 1.NiN 卷积层的参数等于输入的通道数*输出的通道数乘以窗口的平方,然而全连接层的参数的大小等于输入的通道乘以图片的大小乘以输出的通道数。全连接层的参数很多,占用很多的内存,占用很多的计算带宽,很容易出…
最新文章