Linux平台设备驱动开发详解与实践

发布时间:2026/9/28 13:45:33

Linux平台设备驱动开发详解与实践
1. Linux平台设备驱动开发基础在嵌入式Linux开发中平台设备驱动(Platform Device Driver)是一种重要的驱动模型它专门用于管理那些没有物理总线的简单设备。这类设备通常包括LED、按键、蜂鸣器等常见外设。platform_driver_register()和platform_device_register()是Linux内核提供的两个核心API用于实现平台设备和驱动的注册与管理。1.1 平台设备与驱动的基本概念平台总线(Platform Bus)是Linux内核中的一种虚拟总线用于连接那些没有专用物理总线的设备。这种设计使得简单外设也能遵循Linux设备模型实现设备与驱动的分离。平台设备(Platform Device)通过platform_device结构体描述主要包含设备名称(name)设备ID(id)资源信息(resource)私有数据(platform_data)平台驱动(Platform Driver)通过platform_driver结构体描述核心成员包括probe/remove回调函数驱动名称(driver.name)兼容设备表(id_table)2. 平台设备注册详解2.1 platform_device结构体解析struct platform_device { const char *name; int id; struct device dev; u32 num_resources; struct resource *resource; const struct platform_device_id *id_entry; };关键字段说明name设备名称用于总线匹配id设备实例编号dev内嵌的device结构体resource设备资源数组num_resources资源数量2.2 设备资源定义设备资源通过struct resource描述struct resource { resource_size_t start; resource_size_t end; const char *name; unsigned long flags; };常用资源类型标志IORESOURCE_MEM内存映射资源IORESOURCE_IOI/O端口资源IORESOURCE_IRQ中断资源2.3 平台设备注册流程定义设备资源static struct resource pdev_res[] { [0] DEFINE_RES_MEM(0xFDD60000, 0x10), [1] DEFINE_RES_IRQ(32), };初始化platform_device结构体static struct platform_device pdev { .name sample-device, .id 0, .num_resources ARRAY_SIZE(pdev_res), .resource pdev_res, };注册设备int ret platform_device_register(pdev); if (ret) { pr_err(Failed to register platform device\n); return ret; }3. 平台驱动开发实践3.1 platform_driver结构体详解struct platform_driver { int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); struct device_driver driver; const struct platform_device_id *id_table; };关键操作函数probe设备匹配成功后调用remove设备移除时调用3.2 驱动注册实现定义id_tablestatic const struct platform_device_id sample_ids[] { { sample-device, 0 }, { } }; MODULE_DEVICE_TABLE(platform, sample_ids);实现probe函数static int sample_probe(struct platform_device *pdev) { struct resource *mem; void __iomem *regs; mem platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(pdev-dev, No memory resource\n); return -ENODEV; } regs devm_ioremap_resource(pdev-dev, mem); if (IS_ERR(regs)) return PTR_ERR(regs); /* 设备初始化代码 */ return 0; }注册平台驱动static struct platform_driver sample_driver { .driver { .name sample-driver, }, .probe sample_probe, .remove sample_remove, .id_table sample_ids, }; module_platform_driver(sample_driver);4. 设备与驱动的匹配机制4.1 匹配优先级平台总线匹配设备和驱动时按照以下优先级顺序设备树匹配(of_driver_match_device)ACPI匹配(acpi_driver_match_device)id_table匹配名称匹配(strcmp)4.2 匹配函数实现static int platform_match(struct device *dev, struct device_driver *drv) { struct platform_device *pdev to_platform_device(dev); struct platform_driver *pdrv to_platform_driver(drv); /* 设备树匹配 */ if (of_driver_match_device(dev, drv)) return 1; /* ACPI匹配 */ if (acpi_driver_match_device(dev, drv)) return 1; /* id_table匹配 */ if (pdrv-id_table) return platform_match_id(pdrv-id_table, pdev) ! NULL; /* 名称匹配 */ return (strcmp(pdev-name, drv-name) 0); }5. 实战案例LED平台驱动5.1 设备端实现/* 定义GPIO资源 */ static struct resource led_res[] { [0] DEFINE_RES_MEM(0xFDD60000, 0x10), [1] DEFINE_RES_MEM(0xFDD60004, 0x10), }; /* 定义私有数据 */ static unsigned int led_pin 7; /* 定义平台设备 */ static struct platform_device led_pdev { .name platform-led, .id 0, .num_resources ARRAY_SIZE(led_res), .resource led_res, .dev { .platform_data led_pin, }, };5.2 驱动端实现struct led_platform_data { unsigned int pin; }; static int led_probe(struct platform_device *pdev) { struct led_platform_data *pdata dev_get_platdata(pdev-dev); struct resource *mem; void __iomem *regs; /* 获取资源 */ mem platform_get_resource(pdev, IORESOURCE_MEM, 0); regs devm_ioremap_resource(pdev-dev, mem); /* 初始化GPIO */ iowrite32(ioread32(regs) | (1 pdata-pin), regs); /* 注册字符设备 */ /* ... */ return 0; } static struct platform_driver led_driver { .driver { .name platform-led, }, .probe led_probe, /* ... */ };6. 常见问题与调试技巧6.1 匹配失败排查检查/sys/bus/platform/devices和/sys/bus/platform/drivers目录确认设备和驱动的name字段一致检查probe函数是否被调用6.2 资源获取失败处理res platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(pdev-dev, Failed to get MEM resource\n); return -ENXIO; } irq platform_get_irq(pdev, 0); if (irq 0) { dev_err(pdev-dev, Failed to get IRQ\n); return irq; }6.3 内存映射注意事项使用devm_ioremap_resource自动管理资源检查返回的指针是否有效注意资源的大小和对齐7. 现代Linux驱动开发实践7.1 设备树与平台设备的结合sample_device: sample-devicefdd60000 { compatible vendor,sample-device; reg 0xfdd60000 0x1000; interrupts 0 32 4; led-pin 7; };7.2 使用devm_系列函数管理资源/* 自动释放的资源管理 */ regs devm_ioremap_resource(pdev-dev, res); clk devm_clk_get(pdev-dev, NULL); irq devm_request_irq(pdev-dev, irq_num, handler, flags, name, dev);7.3 平台驱动的最佳实践充分利用设备树传递配置信息使用devres机制管理资源实现适当的电源管理回调提供sysfs接口进行调试和控制在实际开发中平台设备驱动模型为简单外设提供了标准化的管理方式使得驱动代码可以更好地与硬件信息分离提高了代码的可维护性和可移植性。通过合理使用platform_device_register()和platform_driver_register()开发者可以构建出符合Linux设备模型的优质驱动。

相关新闻

大型企业产品研发管理体系:用 IPD 打通战略、需求、研发与商业成功 (PPT)

大型企业产品研发管理体系:用 IPD 打通战略、需求、研发与商业成功 (PPT)

2026/9/26 6:49:33

研发管理最难的从来不是“把项目做完”,而是确保企业持续投入资源去做正确的产品,并以可预测的质量、成本和节奏把产品推向市场。大型企业要摆脱“立项靠拍板、需求靠口头、研发靠加班、上市靠运气”的循环,必须建立从市场洞察到生命周期经营…

AI Agent开发中的PLAN-AND-EXECUTE模式解析与实践

AI Agent开发中的PLAN-AND-EXECUTE模式解析与实践

2026/9/27 15:13:30

1. AI Agent开发中的PLAN-AND-EXECUTE模式解析在AI Agent开发领域,PLAN-AND-EXECUTE模式正在成为处理复杂任务的新范式。这种架构将传统ReAct(Reasoning and Action)代理的单步决策过程拆分为明确的规划阶段和执行阶段,就像建筑项…

MiniMax算法与Agent系统的技术演进及应用

MiniMax算法与Agent系统的技术演进及应用

2026/8/23 0:02:26

1. 项目概述:对话MiniMax择因的技术本质这个标题背后探讨的是当前人工智能领域最前沿的Agent技术发展路径。作为从业者,我理解这实际上是在讨论三个关键命题:第一,MiniMax这类新型AI架构的技术原理;第二,Ag…

CANN/GE ACL数据集缓冲区添加函数

CANN/GE ACL数据集缓冲区添加函数

2026/9/28 4:08:17

aclmdlAddDatasetBuffer 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、Te…

用ffmpeg高效批量调整图片尺寸的实战指南

用ffmpeg高效批量调整图片尺寸的实战指南

2026/9/27 1:30:29

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

2026/9/28 2:15:29

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱 【免费下载链接】transformers 🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and mu…

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

2026/9/28 3:14:54

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system sup…

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

2026/9/28 3:58:00

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

2026/9/28 3:47:14

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting mi…

远程协作的工作台整理

远程协作的工作台整理

2026/9/26 14:29:04

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/28 5:05:21

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/26 23:35:16

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…