08、Platform device 资源的获取 ***
📢设备树中的节点被转换为platform_device
后,设备树中的reg
属性、interrupts
属性也会被转换为“resource
”。这时,你可以使用这个函数取出这些资源。
一、Platform device 结构体
以下是更直白简洁的改写版本:
平台设备结构体(platform_device)是Linux内核中用来描述平台设备的容器,定义在"include/linux/platform_device.h"文件中。它的主要成员包括:
struct platform_device {
const char *name; // 设备名称,用于唯一标识设备
int id; // 设备编号(可选,-1表示不需要)
bool id_auto; // 是否自动分配编号
struct device dev; // 设备基础信息(必须正确初始化)
u32 num_resources; // 资源数量
struct resource *resource; // 资源列表指针
const struct platform_device_id *id_entry; // 驱动匹配标识
char *driver_override; // 强制指定驱动名称
struct mfd_cell *mfd_cell; // 复合设备单元(多功能设备使用)
struct pdev_archdata archdata; // 架构相关数据
};
2
3
4
5
6
7
8
9
10
11
12
关键字段说明:
- name:设备名称(必须唯一)
- id:设备编号(可选,设为-1时自动忽略)
- dev:设备基础结构体(必须包含正确的release方法,否则编译报错)
- num_resources & resource:设备资源数量和资源列表(记录内存地址、中断号等硬件资源)
- id_entry:驱动匹配标识符(用于连接设备与驱动)
该结构体通过name和id组合唯一标识设备,配合资源信息(resource)描述设备的硬件特征,最终通过id_entry与驱动程序进行匹配,实现设备管理的核心功能。
二、resource 结构体
以下是更直白的改写版本:
struct resource
结构体用于描述系统中的硬件资源(如内存区域、I/O端口、中断等),定义在内核的/include/linux/ioport.h
文件中。其核心成员如下:
struct resource {
resource_size_t start; // 起始地址(资源开始的位置)
resource_size_t end; // 结束地址(资源结束的位置)
const char *name; // 资源名称(例如"PCI中断"或"内存块")
unsigned long flags; // 属性标志(标记资源的使用规则)
// 其他字段(如父/子资源指针等,用于资源层级管理)
};
2
3
4
5
6
7
关键参数解释:
**start**
资源的起始地址,比如内存的起始位置或I/O端口的起始编号。**end**
资源的结束地址,表示资源占用的范围终点。**name**
一个字符串,用于给资源命名(如"USB控制器内存"),方便调试和管理。**flags**
用二进制位标记资源的属性,例如:- 是否可共享(多个设备能否共用)
- 是否已占用
- 缓存配置(是否需要缓存)
- 其他系统定义的特性
其他成员:
**parent/sibling/child**
:指向资源的父级、同级或子级,形成资源树结构。- 保留字段:未使用的空间,供未来扩展使用(如
ANDROID_KABI_RESERVE
)。
:::
总结:
这个结构体像资源的"身份证",记录资源的位置、名称、规则,以及与其他资源的关系。开发者通过它管理硬件资源的分配和冲突检测。 :::
三、platform_get_resource() 获取
platform_get_resource() 是一个用于获取设备资源信息的函数,定义在 <linux/platform_device.h>
头文件中。它的作用是帮助驱动程序从平台设备中找到特定类型的资源。
函数用法:
struct resource *platform_get_resource(
struct platform_device *pdev, // 要查询的平台设备
unsigned int type, // 资源类型(比如内存、中断等)
unsigned int num // 资源索引号(从0开始)
);
2
3
4
5
简单解释:
作用:这个函数会从设备的资源列表里,根据你指定的类型和编号,找到对应的资源信息。
资源列表:每个平台设备都有一个资源数组,每个条目包含资源的详细信息(如内存地址范围、中断号等)。
返回值:
- 成功时返回资源的结构体指针,可以直接读取资源的起始地址、结束地址等信息。
- 失败时返回
NULL
,这时需要处理错误(比如打印日志或退出驱动初始化)。
使用示例:
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
// 如果没找到第一个内存资源,执行错误处理
pr_err("找不到内存资源!\n");
return -ENODEV;
}
// 成功获取后,可以直接用 res->start 和 res->end 访问地址范围
2
3
4
5
6
7
::: 总结: 这个函数让驱动开发者能快速定位设备的资源(如内存、中断等),方便后续操作(比如申请内存、配置中断)。只需传入设备、资源类型和编号,就能直接拿到资源的具体数据。 :::
四、platform_get_resource() 案例
案例:
五、platform_get_resource实现
platform_get_resource
函数源码如下:
函数分析:
struct resource *r = &dev->resource[i];
这行代码使得不管你是想获取哪一份资源都从第一份资源开始搜索。
if (type == resource_type(r) && num-- == 0)
这行代码首先通过 type == resource_type(r)
判断当前这份资源的类型是否匹配,如果匹配则再通过 num-- == 0
判断是否是你要的,如果不匹配重新提取下一份资源而不会执行 num-- == 0
这一句代码。
通过以上两步就能定位到你要找的资源了,接着把资源返回即可。如果都不匹配就返回NULL
。
六、直接访问 platform_device 结构体的资源数组
struct resource *res_mem = &pdev->resource[0];
在 这种 方法 中, 直接 访 问 platform_device 结 构体 的资 源数 组来 获 取硬 件资 源。pdev->resource 是一个资源数组, 其中存储了设备的硬件资源信息。 通过访问数组的不同索引,可以获取到特定的资源。