Linux设备驱动-platform虚拟总线dya01

平台总线是Linux设备驱动模型中的一种虚拟总线,用于整合不依赖于物理总线的设备。它包括platform_device和platform_driver两个结构体,设备和驱动通过匹配进行交互。在设备启动和驱动注册后,通过probe函数完成驱动初始化。Linux4.0以后,设备树用于管理设备信息,简化驱动匹配过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考连接:https://www.cnblogs.com/deng-tao/p/6026373.html
参考书:<Linux设备驱动开发详解>宋宝华
根据参考资料和同事讨论总结.

摘要: platform的原理及相关结构体

1、什么是platform(平台)总线?

相对于USB、PCI、I2C、SPI等物理总线来说,platform总线是一种虚拟、抽象出来的总线,实际中并不存在这样的总线。

那为什么需要platform总线呢?
其实是Linux设备驱动模型为了保持设备驱动的统一性而虚拟出来的总线。因为对于usb设备、i2c设备、pci设备、spi设备等等,他们与cpu的通信都是直接挂在相应的总线下面与我们的cpu进行数据交互的,但是在我们的嵌入式系统当中,并不是所有的设备都能够归属于这些常见的总线,在嵌入式系统里面,SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设却不依附与此类总线。所以Linux驱动模型为了保持完整性,将这些设备挂在一条虚拟的总线上(platform总线),而不至于使得有些设备挂在总线上,另一些设备没有挂在总线上。

platform总线相关代码:driver\base\platform.c 文件

相关结构体定义:include\linux\platform_device.h 文件中

2.通俗理解

Platform虚拟总线
总线两边分别挂接设备和驱动,设备和驱动互相探测,一旦探测成功(基于设备树风格的匹配,基于ID表,基于设备名和驱动名)就可以对设备进行操作了.

设备驱动的开发,我们可以总结为以下顺序:
定义platform_device
注册platform_device
定义platform_driver
注册platform_driver

单片机是直接拿寄存器控制硬件.
而嵌入式设备因为有操作系统,必须通过驱动来控制硬件设备.

3.platform平台总线工作原理
平台总线体系的工作流程
(1)第一步:系统启动时在bus系统中注册platform
(2)第二步:内核移植的人负责提供platform_device
(3)第三步:写驱动的人负责提供platform_driver
(4)第四步:platform的match函数发现driver和device匹配后,调用driver的probe函数来完成驱动的初始化和安装,然后设备就工作起来了

4.platform总线管理下的2员大将

两个结构体platform_device和platform_driver

对于任何一种Linux设备驱动模型下的总线都由两个部分组成:
描述设备相关的结构体和描述驱动相关的结构体

在platform总线下就是platform_device和platform_driver

(1)platform_device结构体:(include\linux\platform_device.h)

 struct platform_device {           //  platform总线设备
      const char    * name;          //  平台设备的名字
     int id;                 //   ID 是用来区分如果设备名字相同的时候(通过在后面添加一个数字来代表不同的设备,因为有时候有这种需求)
     struct device dev;          //   内置的device结构体
     u32 num_resources;      //   资源结构体数量
     struct resource * resource; //   指向一个资源结构体数组
     const struct platform_device_id *id_entry; //  用来进行与设备驱动匹配用的id_table表
                               /* arch specific additions */
     struct pdev_archdata archdata;        //  自留地    添加自己的东西
 };

platform_device结构体中的struct resource结构体分析:

 struct resource {      // 资源结构体
         resource_size_t start;      // 资源的起始值,如果是地址,那么是物理地址,不是虚拟地址
         resource_size_t end;        // 资源的结束值,如果是地址,那么是物理地址,不是虚拟地址
         const char *name;           // 资源名
         unsigned long flags;        // 资源的标示,用来识别不同的资源
         struct resource *parent, *sibling, *child;   // 资源指针,可以构成链表
 };

(2)platform_driver结构体

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;
};

其中,device_driver结构体定义如下:

struct device_driver {
	const char *name;
	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;

	int (*probe) (struct device *dev);
	int (*remove) (struct device *dev);
	void (*shutdown) (struct device *dev);
	int (*suspend) (struct device *dev,pm_message_t state);
	int (*resume) (struct device *dev);
	const struct attribute_group **groups;

	const struct dev_pm_ops *pm;

	struct driver_private *p;
};

与platform_driver地位对等的i2c_driver,spi_driver,usb_driver等都包含device_driver结构体实例成员,他其实描述了xxx_driver(xxx是总线名)在驱动意义上的一些共性.

在Linux4.0以后,内核直接使用设备树来管理设备信息.设备树中包含寄存器地址,中断号等信息,直接写成一个文本文档,bootloader会将"这棵树"传给内核,内核解析其中的内容,进而展开内核中的platform_device,i2c_client,spi_device等设备. 驱动程序直接从设备树的name进行匹配, 匹配到就可以通过platform_get_resource函数得到设备信息和寄存器信息等,进而控制硬件设备.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值