GoDm@'s Blog

Platform设备模型

版权信息

warning

本文章为博主原创文章。遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。


1. 为什么使用platform?

为了可移植性、兼容性,复用性,实现硬件和驱动的分离,让设备驱动可以在不同的板子上跑。

2. Platform 设备模型适合哪些设备?

在 Linux 内核中,像 USB、PCI、I2C 这种设备可以自动被总线发现。但很多嵌入式系统的 SoC 内部外设(如 GPIO、RTC、UART、LCD、I2C-contrller)是直接通过内存映射(Memory-mapped)访问的,CPU 无法自动“感知”它们的存在。

Platform 总线就是为了管理这些“挂在内存上”的设备而诞生的。

3. 理解 Platform 模型

Platform 模型的核心思想是 “分层”:将硬件信息驱动逻辑分开。它由三个核心部分组成:

  1. Platform Device (设备):描述硬件资源(寄存器地址、中断号等)。
  2. Platform Driver (驱动):实现操作逻辑(如何初始化、读写数据等)。
  3. Platform Bus (总线):作为中介,负责匹配设备和驱动。

我们简单过一遍platform的工作流程,以对这三个部分有个简单的认知。

3.1. Platform 的工作流程

3.1.1. 总览

读取设备树
 → 解析节点
   → 判断“谁来认领这个节点”
     → 创建 platform_device(兜底)
       → platform_driver 注册
         → platform_bus 匹配
           → probe()

先明确一个前提:

3.1.2. step1:内核解析设备树阶段

内核启动过程中,会进入设备树初始化阶段,开始解析设备树的节点。
对每个节点,内核问一个关键的问题:

这个节点,该由谁来处理?

  1. 先问:“是不是‘可枚举总线’设备?”
    例如USB、PCI。
    如果是——跳过设备树创建设备,以后靠总线扫描来创建

  2. 再问:“是不是某个‘专用子系统’设备?”
    例如节点里有一些特殊属性:

    • gpio-controller
    • interrupt-controller
    • clock-controller
    • pinctrl
      如果是——这类节点有对应子系统解析。
  3. 再问:”是不是属于某条总线子设备?“
    例如I2C总线、SPI总线
    如果是——有专门的总线框架解析

这里注意区分I2C控制器和I2C设备,I2C控制器通常是SoC的内部外设,是platform设备,而I2C设备是挂在 I2C 总线上的外设,由I2C 总线框架管理不是 platform 设备

问完之后,没人要你?那你就是 platform 设备。所以platform设备就是兜底规则。

3.1.3. step2:内核创建 platform_device(设备)

即内核将设备“挂”在 platform_bus 上。

内核创建了

struct platform_device *pdev;

其中比较重要的结构体成员:

这一步硬件被“对象化”了。之后GPIO、IRQ、寄存器、电源管理等全部都可以从 pdev->dev 出发统一获取

注意这里引出了platform的核心对象之一——设备

3.1.4. step3:platform_driver 注册(驱动)

这一步是你做的。当你根据platform设备框架编写 platform_driver(驱动逻辑)时,
一定会调用:(后文会详细提到)

module_platform_driver(my_driver);

它类似于 module_init()而这个API的作用是把你写的驱动程序也注册进platform_bus,也就是把驱动挂到platform总线。

所以当你加载你的.ko文件时,驱动程序也注册进了platform总线。

那这里就引出了platform的核心对象之一——驱动

3.1.5. step4:platform_bus 开始做“匹配”

这是 platform 作为总线的核心职责。

我们用伪代码来概括一下总线做的事:

for each platform_device:
    for each platform_driver:
        if (match(device, driver)):
            call driver->probe(device)

匹配机制(Match)
最常用的就是根据 compatible 进行匹配。
优先级大致是:

  1. of_match_table ← 设备树 compatible
  2. id_table
  3. name

整个过程我们的 compatible 就只在这一步发挥作用。

3.1.6. step5:probe() 被调用

驱动和设备匹配成功后就会调用probe()
probe()由你来实现。具体操作细节后文细说

那我们应该在probe里做什么?——让设备(硬件)可用。

典型顺序:

  1. pdev->dev.of_node 读属性
  2. 申请 GPIO / IRQ / 内存
  3. 初始化硬件状态
  4. 注册字符设备 / miscdevice(如果需要)

3.1.7. step6:remove

如果设备被移除或其驱动被卸载,也就是匹配失效,则会调用remove()。

remove()当然也由你来实现。我们后文细说。

4. 使用Platform设备模型

4.1. 省流版

用设备树“声明硬件”,用 platform_driver“实现驱动逻辑”,
内核通过 platform 总线把两者配对,并调用你的 probe()

4.2. step1:在设备树里声明设备

.dts 里写一个节点描述硬件,例如:

mykey {
    compatible = "gdm,mykey";
    key-gpio = <&gpio1 5 GPIO_ACTIVE_LOW>;
    interrupt-parent = <&gpio1>;
    interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
};

4.3. step2:编写platform_driver(驱动逻辑)

4.3.1. 定义匹配表

static const struct of_device_id mykey_of_match[] = {
    { .compatible = "gdm,mykey" },
    { }
};
MODULE_DEVICE_TABLE(of, mykey_of_match);

这一步是在告诉 platform 总线:我能驱动什么设备,我能驱动设备的特征。 给bus的匹配提供信息。

4.3.2. 在 probe() 中完成“设备初始化”

4.3.2.1. 获取设备树节点
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;

后续所有资源都从这里“派生”

4.3.2.2. 获取GPIO【可选】
struct gpio_desc *key_gpio;

key_gpio = devm_gpiod_get(dev, "key", GPIOD_IN);
4.3.2.3. 获取IRQ【可选】
int irq = platform_get_irq(pdev, 0);

作用

4.3.2.4. 注册中断【可选】
devm_request_irq(dev, irq, key_isr,
                 IRQF_TRIGGER_FALLING,
                 "mykey", dev);
4.3.2.5. 其他操作…

4.3.3. remove()

如果你用了:devm_开头的API,那基本上就不需要头疼资源释放的问题

因为platform + devm = 自动资源回收

4.3.4. 定义platform的操作

static struct platform_driver mykey_driver = {
    .probe  = mykey_probe,
    .remove = mykey_remove,
    .driver = {
        .name = "mykey",
        .of_match_table = mykey_of_match,
    },
};

这一步把你的 probe / remove 交给 platform 框架托管。

4.3.5. 注册 driver

在模块的编写中通常这样写:

static int __init leddriver_init(void)
{
	 return module_platform_driver(myled_driver);
}

这一步把 driver
挂到 platform_bus 上。

4.4. step3:像往常一样添加设备

初学者通常没弄清platform的作用,它只负责板级设备的描述、匹配、生命周期管理、硬件资源获取与托管。并不是直接把设备给你创建好了,如果你需要用户态接口,比如read()、write()、ioctl();或者需要设备接口(/dev/xxx),你仍需要自己创建(在probe()中)。

它是一个仓管,你完成一个作品需要什么资源,告诉仓管,仓管从仓库里给你拿资源,然后你来做。


共计约1.7k字。于2025/12/13首次发布,最后更新于2025/12/13。

本文章为博主原创文章。遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

AI辅助创作:本文部分内容由 ChatGPT 5.1 生成,最终版本由作者审核与修改。了解该AI模型

  1. 1. 为什么使用platform?
  2. 2. Platform 设备模型适合哪些设备?
  3. 3. 理解 Platform 模型
    1. 3.1. Platform 的工作流程
  4. 4. 使用Platform设备模型
    1. 4.1. 省流版
    2. 4.2. step1:在设备树里声明设备
    3. 4.3. step2:编写platform_driver(驱动逻辑)
    4. 4.4. step3:像往常一样添加设备