下面我给你一篇内核源码级 + 驱动实战 + 面试友好的完整讲解
👉 Linux Platform 平台设备驱动详解。
这是嵌入式 Linux / 驱动工程师必会核心内容。
一、什么是 Platform 设备驱动?(一句话先记)
Platform 是 Linux 内核中用于描述“非热插拔、SoC 内部外设”的设备模型
📌 典型对象:
- GPIO
- I2C 控制器
- SPI 控制器
- UART
- 定时器
- 看门狗
👉 不是 USB / PCI 这类可枚举总线
二、为什么需要 Platform 总线?
传统问题(老写法)
// 在驱动中直接写死寄存器地址
#define GPIO_BASE 0x01C20800
❌ 缺点:
- 不可移植
- 地址硬编码
- 不支持设备树
- 驱动与硬件强耦合
Platform 的解决方案
硬件信息 → 设备(device)
驱动逻辑 → 驱动(driver)
Platform 总线负责匹配
📌 设备和驱动解耦
三、Platform 架构全景图
+------------------+
| Platform Bus |
+------------------+
↑ ↑
platform_device platform_driver
四、Platform 三大核心结构体(必考)
1️⃣ platform_device(描述硬件)
struct platform_device {
const char *name;
int id;
struct device dev;
u32 num_resources;
struct resource *resource;
};
📌 重点成员:
name:匹配驱动resource:硬件资源(寄存器 / IRQ)
2️⃣ resource(硬件资源)
struct resource {
resource_size_t start;
resource_size_t end;
unsigned long flags;
};
常见 flags:
IORESOURCE_MEM // 寄存器
IORESOURCE_IRQ // 中断
3️⃣ platform_driver(驱动)
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
struct device_driver driver;
};
📌 probe = 驱动入口
五、Platform 匹配机制(面试必问)
1️⃣ 非设备树(旧)
platform_device.name == platform_driver.driver.name
2️⃣ 设备树(主流)
of_match_table
static const struct of_device_id my_of_match[] = {
{ .compatible = "myvendor,mydevice" },
{ }
};
MODULE_DEVICE_TABLE(of, my_of_match);
📌 compatible 是核心
六、Platform 设备注册方式
1️⃣ 非设备树(不推荐)
注册 device
static struct resource my_res[] = {
{
.start = 0x10000000,
.end = 0x10000FFF,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device my_dev = {
.name = "my_plat_dev",
.id = -1,
.resource = my_res,
.num_resources = ARRAY_SIZE(my_res),
};
platform_device_register(&my_dev);
2️⃣ 设备树(主流)
DTS 示例
mydev@10000000 {
compatible = "myvendor,mydevice";
reg = <0x10000000 0x1000>;
interrupts = <10>;
};
📌 设备树自动生成 platform_device
七、Platform 驱动完整示例(设备树)
1️⃣ 驱动代码
static int my_probe(struct platform_device *pdev)
{
struct resource *res;
void __iomem *base;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
printk("platform device probed\n");
return 0;
}
static int my_remove(struct platform_device *pdev)
{
printk("platform device removed\n");
return 0;
}
2️⃣ 驱动注册
static const struct of_device_id my_of_match[] = {
{ .compatible = "myvendor,mydevice" },
{}
};
static struct platform_driver my_driver = {
.probe = my_probe,
.remove = my_remove,
.driver = {
.name = "my_plat_drv",
.of_match_table = my_of_match,
},
};
module_platform_driver(my_driver);
八、Platform 驱动中常用 API(高频)
| API | 作用 |
|---|---|
| platform_get_resource | 获取资源 |
| devm_ioremap_resource | 映射寄存器 |
| platform_get_irq | 获取中断 |
| devm_request_irq | 申请中断 |
| devm_kzalloc | 设备托管内存 |
📌 devm_ = 自动释放
九、为什么 probe 会被调用?
设备树加载
↓
生成 platform_device
↓
platform_driver 注册
↓
匹配 compatible
↓
probe()
📌 不是 main 函数调用
十、Platform 与字符设备关系(必懂)
platform_driver
↓
probe()
↓
注册 char device
↓
创建 /dev/xxx
👉 Platform 负责 “找到硬件”
👉 字符设备负责 “提供用户接口”
十一、常见面试题 & 标准答案
Q1:Platform 和 PCI/USB 区别?
Platform 不支持枚举,靠设备树描述
Q2:probe 什么时候调用?
设备和驱动匹配成功时
Q3:platform_device 从哪来?
设备树 or board 文件
Q4:为什么用 devm_*?
自动资源回收,防泄漏
十二、一句话终极总结(必背)
Platform 是 Linux 中描述 SoC 内部设备的核心机制,
通过设备树生成 device,
通过 compatible 匹配 driver,
probe 完成硬件初始化。
发表回复