1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > Linux设备驱动-platform虚拟总线dya01

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

时间:2024-05-14 08:00:37

相关推荐

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

参考连接:/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函数得到设备信息和寄存器信息等,进而控制硬件设备.

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。