platform总线是学习linux驱动必须要掌握的一个知识点。

一、概念

嵌入式系统中有很多的物理总线:I2c、SPI、USB、uart、PCIE、APB、AHB

linux从2.6起就加入了一套新的驱动管理和注册的机制platform平台总线,是一条虚拟的总线,并不是一个物理的总线。

相比 PCI、USB,它主要用于描述SOC上的片上资源。platform 所描述的资源有一个共同点:在CPU 的总线上直接取址。

平台设备会分到一个名称(用在驱动绑定中)以及一系列诸如地址和中断请求号(IRQ)之类的资源。

设备用platform_device表示,驱动用platform_driver进行注册。

与传统的bus/device/driver机制相比,platform由内核进行统一管理,在驱动中使用资源,提高了代码的安全性和可移植性。

二、platform

1. platform总线两个最重要的结构体

platform维护的所有的驱动都必须要用该结构体定义:

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;

};

该结构体,用于注册驱动到platform总线,

成员含义

probe当驱动和硬件信息匹配成功之后,就会调用probe函数,驱动所有的资源的注册和初始化全部放在probe函数中

remove硬件信息被移除了,或者驱动被卸载了,全部要释放,释放资源的操作就放在该函数中

struct device_driver driver内核维护的所有的驱动必须包含该成员,通常driver-》name用于和设备进行匹配

const struct platform_device_id *id_table往往一个驱动可能能同时支持多个硬件,这些硬件的名字都放在该结构体数组中

我们编写驱动的时候往往需要填充以上几个成员

platform_device

platform总线用于描述设备硬件信息的结构体,包括该硬件的所有资源(io,memory、中断、DMA等等)。

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;

/* MFD cell pointer */

struct mfd_cell *mfd_cell;

/* arch specific additions */

struct pdev_archdata archdata;

};

成员含义

const char*name设备的名字,用于和驱动进行匹配的

struct devicedev内核中维护的所有的设备必须包含该成员,

u32num_resources资源个数

struct resource*resource描述资源

struct devicedev-》release()必须实现,

其中描述硬件信息的成员struct resource

0x139d0000

struct resource {

resource_size_t start; //表示资源的起始值,

resource_size_t end; //表示资源的最后一个字节的地址, 如果是中断,end和satrt相同

const char *name; // 可不写

unsigned long flags; //资源的类型

struct resource *parent, *sibling, *child;

};

flags的类型说明

#define IORESOURCE_MEM 0x00000200 //内存

#define IORESOURCE_IRQ 0x00000400 //中断

内核管理的所有的驱动,都必须包含一个叫struct device_driver成员, //男性描述的硬件,必须包含struct device结构体成员。 //女性

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;

};

其中:

const char *name;

用于和硬件进行匹配。

内核描述硬件,必须包含struct device结构体成员:

struct device {

struct device *parent;

struct device_private *p;

struct kobject kobj;

const char *init_name; /* initial name of the device */

const struct device_type *type;

struct mutex mutex; /* mutex to synchronize calls to

* its driver.

*/

struct bus_type *bus; /* type of bus device is on */

struct device_driver *driver; /* which driver has allocated this

device */

void *platform_data; /* Platform specific data, device

core doesn‘t touch it */

struct dev_pm_info power;

struct dev_pm_domain *pm_domain;

#ifdef CONFIG_PINCTRL

struct dev_pin_info *pins;

#endif

#ifdef CONFIG_NUMA

int numa_node; /* NUMA node this device is close to */

#endif

u64 *dma_mask; /* dma mask (if dma’able device) */

u64 coherent_dma_mask;/* Like dma_mask, but for

alloc_coherent mappings as

not all hardware supports

64 bit addresses for consistent

allocations such descriptors. */

struct device_dma_parameters *dma_parms;

struct list_head dma_pools; /* dma pools (if dma‘ble) */

struct dma_coherent_mem *dma_mem; /* internal for coherent mem

override */

#ifdef CONFIG_DMA_CMA

struct cma *cma_area; /* contiguous memory area for dma

allocations */

#endif

/* arch specific additions */

struct dev_archdata archdata;

struct device_node *of_node; /* associated device tree node */

struct acpi_dev_node acpi_node; /* associated ACPI device node */

dev_t devt; /* dev_t, creates the sysfs “dev” */

u32 id; /* device instance */

spinlock_t devres_lock;

struct list_head devres_head;

struct klist_node knode_class;

struct class *class;

const struct attribute_group **groups; /* optional groups */

void (*release)(struct device *dev);

struct iommu_group *iommu_group;

bool offline_disabled:1;

bool offline:1;

};

其中:

void (*release)(struct device *dev);

不能为空。

2. 如何注册

要用注册一个platform驱动的步骤

1)注册驱动platform_device_register

/**

* platform_device_register - add a platform-level device

* @pdev: platform device we’re adding

*/

int platform_device_register(struct platform_device *pdev)

{

device_initialize(&pdev-》dev);

arch_setup_pdev_archdata(pdev);

return platform_device_add(pdev);

}

2) 注册设备platform_driver_register

#define platform_driver_register(drv)

__platform_driver_register(drv, THIS_MODULE)

三、举例

1. 开发步骤

platform 总线下驱动的开发步骤是:

设备

需要实现的结构体是:platform_device 。

1)初始化 resource 结构变量

2)初始化 platform_device 结构变量

3)向系统注册设备:platform_device_register。

以上三步,必须在设备驱动加载前完成,即执行platform_driver_register()之前,原因是驱动注册时需要匹配内核中所有已注册的设备名。

platform_driver_register()中添加device到内核最终还是调用的device_add函数。

Platform_device_add和device_add最主要的区别是多了一步insert_resource(p, r),即将platform资源(resource)添加进内核,由内核统一管理。

驱动

驱动注册中,需要实现的结构体是:platform_driver 。

在驱动程序的初始化函数中,调用了platform_driver_register()注册 platform_driver 。

linux platform匹配机制,Linux驱动中的platform总线详解相关推荐

  1. Kali linux 2016.2(Rolling)中的payloads模块详解

    payloads模块,也就是shellcode,就是在漏洞利用成功后所要做的事情.在MSF中为我们提供了大量的实用payloads. 当我们执行 Show payloads命令后,显示3列,分别为Ex ...

  2. linux mv 保持目录结构_Linux中的mv命令详解

    mv命令是move的缩写,可以用来移动文件或者将文件改名(move (rename) files),是Linux系统下常用的命令,经常用来备份文件或者目录. 1.命令格式: mv [选项] 源文件或目 ...

  3. Kali linux 2016.2(Rolling)中的auxiliary模块详解

    不多说,直接上干货! root@kali:~# msfconsole__________________________________________________________________ ...

  4. 设备驱动中的ioctl函数详解

    ioctl是iocontrol的缩写,就是IO控制.         行为上 简单来说,如果你在写驱动程序时候,碰到一些IO操作,在逻辑上不能归类到read,不能归类到write,那就可以认为是ioc ...

  5. php正则匹配preg_match,php正则表达式中preg_match函数的详解

    我们之前给大家介绍了php正则表达式的使用,入门,以及验证邮箱地址,那么我们今天就想大家介绍php正则表达式中的函数preg_match,preg_match函数在php正则表达式中的规则是怎样的? ...

  6. python中split啥意思_python中split的用法详解_后端开发

    如何用python正则表达式匹配字符串?_后端开发 用python正则表达式匹配字符串的方法:1.当匹配单个位置的字符串时,可以使用[(.+?)]正则表达式来提取:2.当连续多个位置的字符串匹配时,可 ...

  7. linux驱动之总线详解

    linux驱动 第一章 linux驱动之设备与驱动 第二章 linux驱动之设备树与GPIO子系统 linux驱动之总线详解 linux驱动 一.总线bus 1.bus在linux中文件结构 2.bu ...

  8. Linux驱动开发_设备文件系统详解

    目录 何为设备管理器? Linux下dev的作用 Devfs sysfs kobject udev proc 何为设备管理器? 设备管理器就是负责管理这台电脑上的外设,当我们通过电脑提供的USB口插入 ...

  9. 【Linux驱动开发】设备树详解(二)设备树语法详解

    ​ 活动地址:CSDN21天学习挑战赛 [Linux驱动开发]设备树详解(一)设备树基础介绍 [Linux驱动开发]设备树详解(二)设备树语法详解 [Linux驱动开发]设备树详解(三)设备树Kern ...

最新文章

  1. 在线作图|如何绘制一张好看的点棒图
  2. Linux常用测试命令
  3. 敏捷个人课后练习四主题:我想要什么?
  4. Oracle 表空间信息
  5. [LeetCode] Single Number
  6. TCP为什么是三次握手和四次挥手
  7. 联想服务器支持esxi版本,联想中国(Lenovo China)_服务频道_服务政策
  8. 节点树xmu 1466.祖先极值
  9. 入门机器学习(四)--Logistic回归
  10. flyway版本号_Spring Boot 集成 Flyway 实现数据库版本控制
  11. 记录一下2019年-2020年期间的学习、工作经历
  12. oracle 模拟阻塞,Oracle 阻塞(blocking blocked)介绍和实例演示
  13. Realtek显示芯片方案设计 RTD2270 RTD2281 RTD2513 RTD2525 RTD2556 RTD2785 RTD2795T 2796 VGA DVI HDMI DP转LVDS
  14. 安川机器人原点丢失_安川机器人报错代码:原点位置校准和操作方法
  15. (案例篇)日志易:IT运维分析及海量日志搜索的实践之路(下)
  16. 点击劫持(clickjacking)
  17. 梨子的功效与作用_梨的9种不为人知的价值
  18. 锐龙R3 3300X和R5 3500X 哪个好
  19. mysql查询学生姓名_查询全体学生的姓名及其出生年份 (数据库)
  20. 第一话:今日播种,来日长成一棵Linux参天大树

热门文章

  1. 手持机连不上信道设置为13的AP
  2. MySQL-事务管理(基础)
  3. windows 安装与使用redis
  4. springboot + profile(不同环境读取不同配置)
  5. Mongodb的索引
  6. android-Service和Thread的区别
  7. ASP.NET MVC 学习6、学习使用Code First Migrations功能,把Model的更新同步到DB中
  8. 设置c#windows服务描述及允许服务与桌面交互的几种方法
  9. 微软“SharePoint天天向上”第一期线上活动
  10. ubuntu下vi/vim 的基本使用法