1. Linux驱动开发中的平台总线概述
在嵌入式Linux系统开发中,平台总线(Platform Bus)是最常见的基础驱动模型之一。我第一次接触这个概念是在开发一块定制化的ARM开发板时,当时需要为板载的专用芯片编写驱动,却发现这个芯片并不属于PCI、USB等标准总线。这就是平台总线发挥作用的地方——它为那些没有物理连接总线的SoC内部设备和板载设备提供了标准的驱动模型。
平台总线本质上是一种虚拟总线,内核用platform_bus_type结构体来表示。与真实总线不同,它不需要硬件上的电气连接,而是通过设备树(Device Tree)或ACPI表来建立设备和驱动之间的关联。在实际项目中,大约60%的嵌入式外设驱动都是基于平台总线开发的,包括GPIO控制器、时钟控制器、DMA引擎等SoC内部外设。
关键理解:平台设备(platform_device)代表具体的硬件资源,平台驱动(platform_driver)包含操作这些设备的代码,而平台总线负责将它们匹配起来。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 平台总线驱动的架构设计
2.1 设备与驱动的匹配机制
平台总线最核心的功能就是匹配设备和驱动。在内核启动时会发生以下关键步骤:
-
设备注册:设备信息通过设备树(如
.dts文件)定义,编译为.dtb后被内核解析,生成platform_device结构体。也可以通过platform_device_register()动态注册。 -
驱动注册:驱动模块加载时调用
platform_driver_register(),将platform_driver结构体注册到总线。 -
匹配执行:总线比较设备和驱动的name字段(或使用of_match_table进行设备树匹配),匹配成功后调用驱动的probe()函数。
c复制// 典型匹配过程示例
static int my_probe(struct platform_device *pdev)
{
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
// 获取设备资源并初始化硬件
...
}
static const struct of_device_id my_of_match[] = {
{ .compatible = "vendor,my-device" },
{},
};
static struct platform_driver my_driver = {
.driver = {
.name = "my_device",
.of_match_table = my_of_match,
},
.probe = my_probe,
.remove = my_remove,
};
2.2 设备资源的表示与获取
平台设备通常需要以下资源:
- 内存映射区域(IORESOURCE_MEM)
- 中断号(IORESOURCE_IRQ)
- DMA通道
- GPIO引脚
- 时钟源
这些资源在设备树中定义,驱动通过以下API获取:
c复制// 获取内存区域
void __iomem *regs = devm_ioremap_resource(&pdev->dev, res);
// 获取中断
int irq = platform_get_irq(pdev, 0);
request_irq(irq, handler, flags, name, dev);
// 获取设备树属性
int value;
of_property_read_u32(pdev->dev.of_node, "property-name", &value);
3. 平台总线驱动的实现细节
3.1 设备树的定义规范
设备树是平台总线驱动的"灵魂",一个规范的设备节点应包含:
dts复制my_device: my-device@0x12340000 {
compatible = "vendor,my-device";
reg = <0x12340000 0x1000>;
interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clkctrl 5>;
clock-names = "core";
resets = <&rstctrl 3>;
vendor,specific-prop = <1>;
};
关键属性说明:
compatible:驱动匹配的"身份证",必须与驱动中的of_match_table一致reg:寄存器地址范围,对应IORESOURCE_MEMinterrupts:中断号及触发方式- 厂商自定义属性:通过of_property_read系列函数读取
3.2 驱动代码的完整实现框架
一个完整的平台驱动应包含以下部分:
c复制#include <linux/platform_device.h>
#include <linux/module.
