Day04_总线驱动
1.Platform虚拟总线驱动
核心价值
作用 | 实现机制 | 优势 |
---|---|---|
统一管理片上资源 | 虚拟总线抽象,无需物理连接 | 简化SoC设备管理 |
设备与驱动解耦 | platform_device 描述资源,platform_driver 实现逻辑 | 提高代码复用性和可移植性 |
自动匹配 | 总线通过名称或ID表匹配设备与驱动 | 减少手动绑定代码 |
安全资源访问 | 内核统一分配资源(内存、中断) | 避免硬件冲突 |
扩展思考:在分布式系统(如OpenHarmony)中,虚拟总线概念进一步演化为“软总线”,实现跨设备的服务发现与通信
相关结构体
struct platform_driver{} -结构体
#include <linux/platform_device.h>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_driver是 Linux 内核中用于管理片上资源(如 SoC 外设控制器)的核心结构体,属于 Platform 总线驱动模型的一部分。Platform 总线是一种虚拟总线,用于连接 CPU 直接寻址的设备(如 GPIO、定时器等),实现驱动与设备的分离与动态匹配
关键成员功能说明:
成员 功能说明 是否必需 probe
驱动与设备匹配成功后调用,负责初始化硬件、注册字符设备/中断/DMA 等资源。 必需 remove
驱动卸载或设备移除时调用,用于释放资源(如内存、中断)。 必需 driver
内嵌的 device_driver
结构体,包含驱动名称(.name
)、模块所有者(.owner
)等基础信息。必需 id_table
支持多设备匹配的标识表,用于非设备树场景。当设备名与表中某项匹配时,触发 probe
。可选 of_match_table
设备树匹配表(位于 driver.of_match_table
),通过设备节点的compatible
属性匹配驱动(如{ .compatible = "xxx-gpio" }
)。设备树场景必需 shutdown
/suspend
/resume
设备关机、休眠和唤醒的回调函数,用于电源管理。 可选 注:
driver.owner
通常设为THIS_MODULE
,但现代内核(5.x+)已自动填充,无需显式赋值。driver.name
是传统匹配方式的关键,需与platform_device.name
一致。platform_driver 的注册与注销
驱动需通过以下接口注册到 Platform 总线:
// 注册驱动 int platform_driver_register(struct platform_driver *drv);// 注销驱动 void platform_driver_unregister(struct platform_driver *drv);
典型驱动框架示例:
#include <linux/platform_device.h> #include <linux/module.h>static int my_probe(struct platform_device *pdev) {printk("Device matched! Resource: MEM 0x%x, IRQ %d\n",pdev->resource[0].start, pdev->resource[1].start);// 初始化硬件、注册字符设备等return 0; }static int my_remove(struct platform_device *pdev) {// 释放资源return 0; }static const struct of_device_id my_of_match[] = {{ .compatible = "my-device" }, // 设备树匹配标识{ } }; MODULE_DEVICE_TABLE(of, my_of_match);static struct platform_driver my_driver = {.driver = {.name = "my_driver",.of_match_table = my_of_match,},.probe = my_probe,.remove = my_remove, };module_platform_driver(my_driver); // 自动生成 init/exit 函数 MODULE_LICENSE("GPL");
设备匹配机制
Platform 总线通过以下方式匹配设备与驱动:
- 设备树(DT)优先 设备节点的
compatible
属性与driver.of_match_table
匹配(如"my-device"
)。- 传统名称匹配 若未使用设备树,则比较
platform_device.name
与driver.name
(如"my_driver"
)。- ID 表扩展匹配 通过
id_table
支持多设备名匹配(如{"deviceA"}, {"deviceB"}
)。资源获取与操作
- 硬件资源访问: 在
probe
函数中,通过platform_device
获取内存、中断等资源:struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); int irq = platform_get_irq(pdev, 0);
- 设备树参数解析: 使用of_property_read_u32() 等接口读取设备树中的自定义属性(如寄存器地址)。
应用场景与优势
- 统一管理片上外设 用于 GPIO、ADC、PWM 等非标准总线设备,避免为每个外设实现独立总线驱动。
- 驱动与硬件解耦 设备资源(地址、中断)通过设备树或
platform_device
描述,驱动无需硬编码,提升可移植性。- 支持热插拔与电源管理 通过
suspend
/resume
实现低功耗模式,shutdown
确保安全断电。总结
platform_driver
是 Linux 驱动开发的核心抽象层,通过分离设备描述与驱动逻辑,显著提升代码复用性和可维护性。开发者需重点关注:
- 匹配机制:设备树兼容性 > 名称匹配 > ID 表。
- 生命周期管理:资源初始化在
probe
中完成,清理在remove
中实现。- 资源获取:利用
platform_get_resource()
等接口安全访问硬件资源。
结构体关系
struct platform_driver{} //device的platform包装struct platform_device_id{} //非设备树设备,id信息匹配结构体struct device_drive{} //设备驱动核心结构体struct of_device_id{} //设备树设备,compatible匹配结构体struct bus_type{} //设备驱动归属总线类型结构体struct platform_device{} //device_drive的platform包装struct device{} //设备核心结构体struct device_node{} //设备树节点信息结构体struct device_type{} //...struct bus_type{}struct device_drive{}struct of_device_id{}struct bus_type{}