前言

区分设备驱动模型平台设备驱动模型

设备驱动模型 可以理解为 总线、设备、驱动

平台设备驱动模型 就是那些 Linux 内核管理没有物理总线(即是不需要特殊时序控制的设备)(也是Linux内核没有自动创建相应驱动总线的设备类型)的设备的一套 Linux 平台总线、平台模型、平台驱动的模型。

7. 平台设备驱动

为解决驱动代码和设备信息耦合问题,linux提出了设备驱动模型。

注意,前面的总线、设备、驱动是一个软件层面的抽象,与 SOC 中物理总线概念不一样。

物理总线:芯片与各个功能外设之间传送信息的公共通信干线,包括数据总线、地址总线和控制总线,以此来传输各种通信时序

驱动总线:负责管理驱动和设备。制定设备和驱动的匹配规则。一旦总线上注册了新设备/驱动,总线便执行匹配程序。

对于常见的 I2C、SPI、USB物理总线Linux 内核都会自动创建与之对应的 驱动总线。所以 I2C设备、SPI设备、USB设备都会挂在在相应的总线上。

相对的,实际项目开发中还有很多结构简单的设备是不需要特殊的时序控制的。也就没有相应的物理总线,Linux 也不会为它们创建相应的驱动总线。如 LED、RTC时钟、按键等等。

但是为了这些简单的设备也能遵循设备驱动模型,Linux 内核引入了一种虚拟总线--平台总线

平台总线 用于管理、挂在那些没有物理总线的设备,且,这些设备被称为平台设备,对应的设备驱动被称为平台驱动

平台设备使用 platform_device 结构体进行表示,继承了设备驱动模型中的 device 结构体。

平台驱动使用 platform_driver 结构体进行表示,继承了设备驱动模型中的 device_driver 结构体。

7.1 平台总线

Linux内核只有一条平台总线,用于图一管理简单设备--platform_bus_type

7.1.1 平台总线注册和匹配方式

最先比较

  • 最先比较 platform_device.driver_overrideplatform_driver.driver.name

  • 可以设置 platform_devicedriver_override,强制选择某个 platform_driver

其次比较

  • 其次比较 platform_device.nameplatform_driver.id_table[i].name

  • platform_driver.id_tableplatform_device_id 指针,表示该 drv 支持若干个 device,它里面列出了各个 device{.name, .driver_data},其中的 name 表示该 drv 支持的设备的名字,driver_data是些提供给该 device 的私有数据。

最后比较

  • 最后比较 platform_device.nameplatform_driver.driver.name

  • 由于 platform_driver.id_table 可能为空,所以,接下来就可以使用 platform_driver.driver.name 来匹配。

7.1.2 源码分析

平台总线

  • 内核使用 bus_type 来抽象系统中的总线。相应地,内核使用 platform_bus_type 来描述平台总线。
  • 源码:
struct bus_type platform_bus_type = {

    .name           = "platform",
.dev_groups = platform_dev_groups,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops, }; EXPORT_SYMBOL_GPL(platform_bus_type);
  • 位于 内核源码/driver/base/platform.c

  • 该总线在Linux内核启动的时候自动进行注册

  • 平台总线初始化函数源码:

int __init platform_bus_init(void){
int error;
...
error = bus_register(&platform_bus_type);
...
return error;}
  • 位于 内核源码/driver/base/platform.c
  • error = bus_register(&platform_bus_type); 就是向Linux内核注册 plateform_bus_type 平台总线。

建议:以上匹配规则及源码,可以追踪函数 platform_match 源码来分析。

7.2 平台设备

7.2.1 platform_device

平台设备

  • 使用 platform_device 描述平台设备。
  • 源码:
struct platform_device {
const char *name;
int id;
struct device dev;
u32 num_resources;
struct resource *resource;
const struct platform_device_id *id_entry;
/* 省略部分成员 */
};
  • 位于 内核源码/include/linux/platform_device.h
  • name:设备名称,总线进行匹配时,会比较设备和驱动的名称是否一致;
  • id:指定设备的编号,Linux支持同名的设备,而同名设备之间则是通过该编号进行区分;
  • dev:Linux设备模型中的device结构体,platform_device 通过继承该结构体可复用它的相关代码,方便内核管理平台设备;
  • num_resources:记录资源的个数,当结构体成员 resource 存放的是数组时,需要记录 resource 数组的个数,内核提供了宏定义 ARRAY_SIZE 用于计算数组的个数;
  • resource:平台设备提供给驱动的资源,如irq,dma,内存等等;
  • id_entry:平台总线提供的另一种匹配方式,原理依然是通过比较字符串,这里的 id_entry 用于保存匹配的结果;

7.2.2 设备信息

平台设备的工作是为 驱动程序 提供 设备信息。包括 硬件信息 和 软件信息。

  • 硬件信息:驱动程序需要使用到的寄存器、中断号、内存资源、IO口等等;
  • 软件信息:以太网设备中的 MAC 地址、I2C 设备中的设备地址等等。

硬件信息

  • 硬件信息使用 struct resource 来保存设备所提供的资源。
  • 源码:
/**
* Resources are tree-like, allowing nesting etc..
*/
struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
/* 省略部分成员 */
};
  • 位于 内核源码/include/linux/ioport.h
  • name:资源名字,可为 NULL;
  • start、end:指定资源的起始地址及结束地址;
    • 对于 IORESOURCE_IO 和 IORESOURCE_MEM 是有起始和结束地址的,若只有一个引脚或者一个通道,那么 start == end
  • flags:用于指定资源的类型,在 Linux 中,资源包括I/O、Memory、Register、IRQ、DMA、Bus等多种类型,如:
    • IORESOURCE_IO:IO 地址空间,对应于 IO 端口映射方式;
    • IORESOURCE_MEM:外设可直接寻址的地址空间;
    • IORESOURCE_IRQ:指定该设备使用哪个中断;
    • IORESOURCE_DMA:指定 DMA 通道。

设备驱动程序主要目的还是操作设备的寄存器。

不同架构的计算机提供不同的操作接口,主要有IO端口映射IO内存映射两种方式。

IO端口映射方式:

  • 只能通过专门的接口函数才能访问。

IO内存映射方式:

  • 可以像内存一样访问,去读写寄存器。

软件信息

  • 软件信息需要以私有数据保存;
  • platform_device 结构体中继承有 device 结构体,成员为 dev,该结构体里面的 platform_data 可以用于保存设备的私有数据。
    • platform__datavoid * 类型的万能指针,所以,只需要把私有数据的地址付给 platform_data 即可。

7.2.3 注册/注销平台设备

注册:platform_device_register

  • 注册平台设备,挂在到平台总线上。
  • 函数原型:int platform_device_register(struct platform_device *pdev);位于 内核源码/drivers/base/platform.c
    • pdedplatform_device 类型结构体指针;
    • 返回:
      • 成功:0;
      • 失败:负数。

注销:platform_device_unregister

  • 注销平台设备。
  • 函数原型:void platform_device_unregister(struct platform_device *pdev);位于 **

    内核源码/drivers/base/platform.c**。

    • pdedplatform_device 类型结构体指针;

7.3 平台驱动

7.3.1 platform_driver

平台驱动

  • 使用 platform_driver 描述平台驱动。
  • 源码:
struct platform_driver {

    int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
};
  • 位于 内核源码/include/platform_device.h

  • probe:匹配成功后执行的回调函数。

  • remove:移除某个平台设备是的回调函数。

  • driver:Linux 设备模型中用于抽象驱动的 device_driver 结构体,platform_driver 继承该结构体,也就获取了设备模型驱动对象的特性。

  • id_table:表示该驱动能够兼容的设备类型。

  • platform_device_id

    • name:指定驱动名称。(用于和 platform_device 中的 name 比较,匹配。)
    • driver_data:用于保存设备的配置。
    • 源码:
struct platform_device_id
{
char name[PLATFORM_NAME_SIZE];
kernel_ulong_t driver_data;
};

7.3.2 注册/注销平台驱动

注册:platform_driver_register

  • 注册平台驱动,挂在到平台总线上。
  • 函数原型:int platform_driver_register(struct platform_driver *drv)
    • drvplatform_driver 类型结构体指针;
    • 返回:
      • 成功:0;
      • 失败:负数。

注销:platform_driver_unregister

  • 注销平台启动驱动。
  • 函数原型:void platform_driver_unregister(struct platform_driver *drv);位于 **

    内核源码/drivers/base/platform.c**。

    • drvplatform_driver 类型结构体指针;

7.3.3 平台驱动获取设备信息

首先要知道的是,平台设备的硬件信息保存在 resource 结构体中。而软件信息则保存在 platform_data 中。

获取硬件信息:platform_get_resource

  • 获取平台设备提供的资源结构体。一般用在 probe 函数中。、

  • 函数原型:struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num);

  • dev:指定获取哪个平台设备的资源;

  • type:指定获取资源的类型,如IORESOURCE_MEM、IORESOURCE_IO等;

  • num:指定要获取的资源编号。每个设备所需要的资源的个数是不一样的。且不同资源的编号是不一样的。

  • 返回:

    • 成功:struct resouce 结构体类型指针;
    • 失败:NULL。
  • 若要获取的资源类型为 IORESOURCE_IRQ,平台设备驱动还提供以下函数接口,来获取中断引脚。

    • 函数原型:int platform_get_irq(struct platform_device *pdev, unsigned int num)

      • pedv:指定需要获取哪个平台设备的资源;
      • num:指定要获取的资源编号。
    • 返回:
      • 成功:可用中断号;
      • 失败:负数。

获取软件信息:dev_get_platdata

* dev:struct device 结构体类型指针。

static inline void *dev_get_platdata(const struct device *dev)
{
return dev->platform_data;
}

参考

【linux】驱动-7-平台设备驱动的更多相关文章

  1. 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联

    转载自:http://www.kancloud.cn/yueqian_scut/emlinux/106829 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sy ...

  2. [kernel]字符设备驱动、平台设备驱动、设备驱动模型、sysfs几者之间的比较和关联

    转自:http://www.2cto.com/kf/201510/444943.html Linux驱动开发经验总结,绝对干货! 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动 ...

  3. Linux驱动之平台设备驱动模型简析(驱动分离分层概念的建立)

    Linux设备模型的目的:为内核建立一个统一的设备模型,从而有一个对系统结构的一般性抽象描述.换句话说,Linux设备模型提取了设备操作的共同属性,进行抽象,并将这部分共同的属性在内核中实现,而为需要 ...

  4. Linux Platform devices 平台设备驱动

    设备总线驱动模型:http://blog.csdn.net/lizuobin2/article/details/51570196 本文主要参考:http://www.wowotech.net/devi ...

  5. 【Linux高级驱动】平台设备驱动机制的编程流程与编译进内核

    [平台设备驱动机制的编程流程] [如何将驱动静态的编译进内核镜像] 1.添加资源(dev-led.c) 1.1:一般来说,系统习惯上将资源放在arch/arm/plat-samsung/目录中 cp ...

  6. 嵌入式Linux驱动学习之路(十七)驱动程序分层分离概念-平台设备驱动

    平台设备驱动: 包含BUS(总线).DEVICE.DRIVER. DEVICE:硬件相关的代码 DRIVER:比较稳定的代码 BUS有一个driver链表和device链表. ①把device放入bu ...

  7. 【Linux高级驱动】linux设备驱动模型之平台设备驱动机制

    [1:引言: linux字符设备驱动的基本编程流程] 1.实现模块加载函数  a.申请主设备号    register_chrdev(major,name,file_operations);  b.创 ...

  8. Linux驱动之平台设备

    <平台设备设备驱动> a:背景: 平台总线是Linux2.6的设备驱动模型中,关心总线,设备和驱动这3个实体.一个现实的Linux设备和驱动通常需要挂接在一种总线上(比如本身依附于PCI, ...

  9. Linux驱动设计——字符设备驱动(一)

    Linux字符设别驱动结构 cdev结构体 struct cdev { struct kobject kobj; struct module *owner; const struct file_ope ...

随机推荐

  1. free HTTPS for website! & SSL & TLS & HTTP/2 & SPDY

    HTTPS for website! 1 1 1 # OK (bugs === main domain temporarily OK) # sub domain allways OK! # partl ...

  2. JSON-LD 结构化数据

    JSON-LD 结构化数据 SEO JSON-LD JSON for Linking Data JSON 链接数据 https://json-ld.org/ https://en.wikipedia. ...

  3. node.js & create file

    node.js & create file node js create file if not exists https://nodejs.org/api/fs.html#fs_fs_ope ...

  4. Github & DMCA Takedown & git remove history

    Github & DMCA Takedown & git remove history Github & DMCA Takedown Policy Removing files ...

  5. Dart: 请求graphql数据

    import 'package:http/http.dart' as http; const url = "http://127.0.0.1:4000/graphql"; main ...

  6. NGK内存将为全球投资者创造新的财富增长机会

    2020年,随着BTC的持续上涨带动了整个区块链市场的持续加温,同时金融市场也对金融体制做出了改变,关于金融和区块链的结合越来越被人们所认可,在此基础上,DeFi行业借此迎来了快速发展,据不完全统计, ...

  7. 07.k近邻算法kNN

    1.将数据分为测试数据和预测数据 2.数据分为data和target,data是矩阵,target是向量 3.将每条data(向量)绘制在坐标系中,就得到了一系列的点 4.根据每条data的targe ...

  8. Scrapy项目_阳光热线问政平台

    目的: 爬取阳光热线问政平台问题中每个帖子的标题.详情URL.详情内容.图片以及发布时间 步骤: 1.创建爬虫项目 1 scrapy startproject yangguang 2 cd yangg ...

  9. 1047 Student List for Course ——PAT甲级真题

    1047 Student List for Course Zhejiang University has 40,000 students and provides 2,500 courses. Now ...

  10. 学习js、jquery、vue实现部分组件

    通过js实现radio小组件,最终效果如下 html代码: <!DOCTYPE html> <html lang="en"> <head> &l ...