平台设备驱动:platform bus 与设备树
平台设备驱动platform bus 与设备树嵌入式 SoC 上的片上外设I2C、SPI、UART、GPIO 控制器等挂在 platform 总线上。这篇讲 platform 驱动框架、设备树 DTS 语法、驱动和设备怎么匹配以及现代 Linux 驱动的标准写法。大家好我是黒漂技术佬。前面讲的字符设备驱动是直接注册 cdev但实际嵌入式驱动不是这么写的。SoC 上的外设比如 I2C 控制器、SPI 控制器、GPIO 控制器都挂在 platform 总线上驱动要按 platform 驱动的框架来写。再加上设备树Device Tree硬件信息从代码里分离出来不用每个板子都改驱动代码。这篇讲 platform 总线、设备树、以及现代 Linux 驱动的标准结构。一、platform 总线为什么需要 platform 总线Linux 有 PCI、USB 等总线设备可以被枚举扫描出来。但 SoC 内部的外设是集成的没法动态枚举地址都是固定的。所以发明了 platform 总线专门挂这类「平台设备」。平台设备 平台驱动和其他总线一样分设备和驱动两边平台设备platform_device描述硬件信息地址、中断、资源 平台驱动platform_driver驱动代码匹配设备后初始化匹配上了就调用驱动的 probe 函数。优点硬件信息和驱动代码分离一个驱动可以支持多个同类型设备符合 Linux 设备模型自动生成 sysfs 节点二、平台驱动结构定义 platform_driver#includelinux/platform_device.hstaticintmy_probe(structplatform_device*pdev){// 匹配成功在这里初始化设备// 拿资源、注册字符设备、申请中断...return0;}staticintmy_remove(structplatform_device*pdev){// 卸载时清理return0;}staticconststructof_device_idmy_of_match[]{{.compatiblevendor,my-device},{/* sentinel */}};MODULE_DEVICE_TABLE(of,my_of_match);staticstructplatform_drivermy_driver{.probemy_probe,.removemy_remove,.driver{.namemy-device,.of_match_tablemy_of_match,// 设备树匹配表},};module_platform_driver(my_driver);module_platform_driver 宏代替手动写 module_init/module_exitmodule_platform_driver(my_driver);展开就是注册和注销 platform_driver 的代码。probe 函数匹配成功后调用驱动初始化的核心从设备树或资源里拿硬件信息寄存器地址、中断号映射寄存器地址申请中断注册字符设备 / 输入设备 / 其他子系统设备初始化硬件remove 函数卸载时调用probe 里申请的资源都要在这里释放。三、设备树Device Tree是什么为什么要有设备树以前 ARM Linux 把硬件信息硬编码在内核里每个板子一份代码内核里堆满了板级文件很乱。设备树把硬件描述从内核代码里抽出来用一个数据结构描述板子上有什么设备、地址多少、中断多少。内核启动时解析设备树动态创建设备。同一个内核镜像配上不同的 dtb设备树二进制就能跑在不同板子上。设备树文件.dts设备树源文件文本格式描述硬件.dtsi设备树头文件公共部分可以 include.dtb编译后的二进制bootloader 加载到内存传给内核基本结构树形结构每个节点代表一个设备/ { model My Board; compatible vendor,my-board; soc { compatible simple-bus; uart10000000 { compatible vendor,uart-1.0; reg 0x10000000 0x1000; interrupts 12; status okay; }; }; };四、DTS 基本语法节点节点名地址 { 属性 值; 子节点 { ... }; };节点名一般格式设备名单元地址属性类型1. 空属性布尔值property; // 存在就是真不存在就是假2. 32位无符号整数property 0x1234 5678; // 一个或多个32位数用包起来3. 字符串property hello;4. 字符串列表property abc, def, ghi;5. 字节数组property [01 02 03 04];常用属性compatible最关键的属性用来匹配驱动。compatible vendor,device-name;一般是「厂商,设备名」的格式。驱动里 of_match_table 里有对应的字符串就匹配上。可以有多个从前往后匹配compatible vendor,chip-uart, generic-uart;reg设备的寄存器地址范围reg 起始地址 长度;可以有多段reg 0x10000000 0x1000, 0x20000000 0x2000;interrupts中断号interrupt-parent gic; interrupts 0 12 4;具体格式取决于中断控制器。status设备状态okay启用disabled禁用fail故障#address-cells / #size-cells子节点的 reg 属性用几个 cell 表示地址、几个表示长度soc { #address-cells 1; // 地址用1个32位数 #size-cells 1; // 长度用1个32位数 };64位地址的话就是#address-cells 2。引用节点用 label 引用uart0: uart10000000 { ... }; // 别处引用 uart0 { status okay; };头文件 include#include chip.dtsi.dtsi 放通用的 SoC 部分板子级的 .dts 引用并修改。五、驱动里读取设备树属性拿到设备节点structdevice_node*nppdev-dev.of_node;读整数u32 val;of_property_read_u32(np,property-name,val);// 读数组u32 vals[4];of_property_read_u32_array(np,property-name,vals,4);读字符串constchar*str;of_property_read_string(np,compatible,str);读布尔值if(of_property_read_bool(np,some-flag)){// 属性存在}获取资源寄存器地址、中断寄存器地址structresource*res;resplatform_get_resource(pdev,IORESOURCE_MEM,0);// 映射void__iomem*basedevm_ioremap_resource(pdev-dev,res);中断号intirqplatform_get_irq(pdev,0);devm_ 系列函数托管资源带 devm_ 前缀的函数分配的资源会在设备释放时自动释放不用手动清理remove 函数省事很多。devm_ioremap_resource()// 自动释放的IO映射devm_kmalloc()// 自动释放的内存devm_request_irq()// 自动释放的中断devm_kzalloc()// 自动释放的清零内存推荐尽量用 devm_ 版本省得漏释放。六、platform 驱动完整示例框架#includelinux/module.h#includelinux/platform_device.h#includelinux/of.h#includelinux/io.h#includelinux/interrupt.hstructmy_dev{void__iomem*base;intirq;// ... 其他私有数据};staticconststructof_device_idmy_of_match[]{{.compatiblevendor,my-device},{}};MODULE_DEVICE_TABLE(of,my_of_match);staticirqreturn_tmy_irq(intirq,void*dev_id){// 中断处理returnIRQ_HANDLED;}staticintmy_probe(structplatform_device*pdev){structmy_dev*dev;structresource*res;intret;// 分配私有数据devm自动释放devdevm_kzalloc(pdev-dev,sizeof(*dev),GFP_KERNEL);if(!dev)return-ENOMEM;// 获取寄存器资源resplatform_get_resource(pdev,IORESOURCE_MEM,0);dev-basedevm_ioremap_resource(pdev-dev,res);if(IS_ERR(dev-base))returnPTR_ERR(dev-base);// 获取中断号dev-irqplatform_get_irq(pdev,0);if(dev-irq0)returndev-irq;// 申请中断retdevm_request_irq(pdev-dev,dev-irq,my_irq,IRQF_TRIGGER_RISING,my_dev,dev);if(ret)returnret;// 保存私有数据platform_set_drvdata(pdev,dev);// 初始化硬件...pr_info(my-device probed\n);return0;}staticintmy_remove(structplatform_device*pdev){// 用了devm的话大部分资源自动释放// 这里做一些额外清理pr_info(my-device removed\n);return0;}staticstructplatform_drivermy_driver{.probemy_probe,.removemy_remove,.driver{.namemy-device,.of_match_tablemy_of_match,},};module_platform_driver(my_driver);MODULE_LICENSE(GPL);MODULE_AUTHOR(Heipiao);MODULE_DESCRIPTION(Platform driver example);对应的设备树节点my_device10000000 { compatible vendor,my-device; reg 0x10000000 0x1000; interrupts 25; status okay; };七、设备树匹配流程内核解析 DTB创建设备节点platform 总线创建设备驱动注册时遍历设备比较 compatible 字符串匹配上了调用 probe匹配优先级of_match_table设备树匹配优先acpi_match_tableACPIx86用name 字符串匹配老式的设备树驱动主要靠 of_match_table。八、常见坑坑 1compatible 字符串不匹配驱动里写的和 dts 里的不一样probe 根本不调用。检查拼写、大小写、厂商前缀。坑 2reg 地址长度不对reg 的长度错了ioremap 映射范围不对访问寄存器越界。坑 3中断号格式不对不同中断控制器的 interrupts 属性格式不一样几 cell、每个的含义要查对应 SoC 的文档。坑 4忘了加 MODULE_DEVICE_TABLE不加的话自动加载模块机制识别不了设备插上不会自动加载驱动。坑 5devm 资源和手动释放混着来一部分用 devm 一部分手动释放顺序容易搞反出错。要么全用 devm要么都手动。坑 6probe 失败没回滚probe 中间某一步失败前面申请的资源要释放。用 devm 可以省很多事但非 devm 的要手动回滚。九、本篇小结platform 总线挂 SoC 片上外设分为平台设备和平台驱动匹配后调用 probe设备树 DTS把硬件信息从内核代码分离描述设备树结构编译成 dtb 传给内核DTS 语法节点、属性、compatible、reg、interrupts、statusplatform_driverprobe 初始化、remove 清理、of_match_table 匹配表驱动读取设备树of_property_read_* 读属性platform_get_resource 拿资源devm_ 系列设备托管资源自动释放减少 remove 工作量和泄漏module_platform_driver简化注册注销的宏匹配靠 compatible 字符串驱动和 dts 里要一致下一篇讲GPIO 子系统与 pinctrlLinux 下怎么操作 GPIO、怎么用 gpiolib、pinctrl 引脚复用。我是黒漂技术佬。

相关新闻

K4A8G165WG-BCWE000选型指南:三星DDR4 x16产品线对比与商业级/工业级选型建议

K4A8G165WG-BCWE000选型指南:三星DDR4 x16产品线对比与商业级/工业级选型建议

K4A8G165WG-BCWE000:三星8Gb DDR4 SDRAM内存颗粒深度解析 在现代数据中心、高性能计算系统以及各类需要高带宽内存支持的嵌入式平台中,DDR4 SDRAM凭借其成熟的生态系统和平衡的性能功耗比,依然是系统设计的关键组件。三星电子(Sa…

2026/7/10 11:47:02阅读更多 →
MongoDB 7.0 实战:从零到一构建学生信息库,完成5类CRUD操作

MongoDB 7.0 实战:从零到一构建学生信息库,完成5类CRUD操作

MongoDB 7.0 实战:从零构建学生信息库的5类CRUD操作全解析 在数字化校园管理系统中,学生信息的高效存储与快速检索一直是技术实现的核心难点。传统关系型数据库在面对频繁变动的学生档案、多样化的课外活动记录以及动态的成绩管理需求时,往往…

2026/7/10 11:42:01阅读更多 →
GKD_THS_List技术选型与订阅源架构设计:构建高性能自动化规则管理平台

GKD_THS_List技术选型与订阅源架构设计:构建高性能自动化规则管理平台

GKD_THS_List技术选型与订阅源架构设计:构建高性能自动化规则管理平台 【免费下载链接】GKD_THS_List GKD第三方订阅收录名单 项目地址: https://gitcode.com/gh_mirrors/gk/GKD_THS_List GKD_THS_List作为GKD自动化工具的第三方订阅收录平台,其核…

2026/7/10 11:42:01阅读更多 →
2026年AI大模型API加速系统权威选购指南:主流服务商性能与成本全维度排名推荐

2026年AI大模型API加速系统权威选购指南:主流服务商性能与成本全维度排名推荐

API加速系统成企业AI落地核心网关 本次评测覆盖全场景需求2026年AI大模型技术已经跨过早期验证阶段,全面进入规模化落地周期,国内市场日均AI Token调用总量突破140万亿,AI大模型API加速系统的定位早已超出最初简单的协议转发工具属性&#xf…

2026/7/10 12:52:14阅读更多 →
PMC每天加班排产还有没有发展前景?2026年职业突围指南

PMC每天加班排产还有没有发展前景?2026年职业突围指南

最近有好几个做生产的学弟学妹来问:每天被生产计划、物料需求、紧急订单追着跑,加班到深夜还在手动对Excel,感觉自己在干体力活,这岗位到底还有没有未来?作为在制造业供应链方向摸爬滚打了好几年、跟无数PMC打过交道的…

2026/7/10 12:52:14阅读更多 →
如何快速上手PilotGo-plugin-syscare:5分钟完成热补丁部署

如何快速上手PilotGo-plugin-syscare:5分钟完成热补丁部署

如何快速上手PilotGo-plugin-syscare:5分钟完成热补丁部署 【免费下载链接】PilotGo-plugin-syscare Introduce SysCare to PilotGo platform. 项目地址: https://gitcode.com/openeuler/PilotGo-plugin-syscare 前往项目官网免费下载:https://ar…

2026/7/10 12:52:14阅读更多 →
智读致用《思辨与立场》08|你不缺结论,缺的是一把看得见推理漏洞的尺子

智读致用《思辨与立场》08|你不缺结论,缺的是一把看得见推理漏洞的尺子

上一章我学会了拆解思维——把一团模糊的想法拆成八个零件,看清自己到底是怎么得出结论的。 可拆完之后,又一个问题冒出来了:我知道自己是怎么想的了,但我怎么知道自己想得对不对? 零件拆开了,但我用什么…

2026/7/10 12:52:14阅读更多 →
openeuler/yocto-meta-openembedded与OE-core集成实战:打造高效嵌入式开发环境

openeuler/yocto-meta-openembedded与OE-core集成实战:打造高效嵌入式开发环境

openeuler/yocto-meta-openembedded与OE-core集成实战:打造高效嵌入式开发环境 【免费下载链接】yocto-meta-openembedded Collection of layers for the OE-core universe 项目地址: https://gitcode.com/openeuler/yocto-meta-openembedded 前往项目官网免…

2026/7/10 12:52:14阅读更多 →
如何通过许可采购实现竞争优势?深度解析

如何通过许可采购实现竞争优势?深度解析

我在企业软件资产管理领域摸爬滚打了二十年,见过太多公司在软件采购上栽跟头。最常见的场景是:CFO看着每年几千万的软件账单皱眉头,CIO则抱怨预算永远不够用,而研发团队还在为拿不到关键的仿真许可而耽误进度。很多人把软件许可采…

2026/7/10 12:47:14阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/10 12:10:00阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/10 12:29:21阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/10 4:59:05阅读更多 →
浏览器缓存行为深度解析:Chrome/Firefox/Safari 对 304 响应的 5 种触发场景对比

浏览器缓存行为深度解析:Chrome/Firefox/Safari 对 304 响应的 5 种触发场景对比

浏览器缓存行为深度解析:Chrome/Firefox/Safari 对 304 响应的 5 种触发场景对比当你在浏览器地址栏敲入一个网址时,背后可能隐藏着一场关于"要不要重新下载资源"的精密博弈。这场博弈的裁判是HTTP缓存机制,而304状态码则是这场博弈…

2026/7/10 0:00:01阅读更多 →
RoboWits:面向创造性问题求解的双臂机器人认知推理基准

RoboWits:面向创造性问题求解的双臂机器人认知推理基准

1. 项目概述:这不是又一个机器人抓取数据集,而是一次对“思考力”的压力测试 RoboWits——这个名字里藏着两个关键信号:“Robo”直指物理世界中的具身智能体,“Wits”则毫不掩饰地指向人类最核心的认知能力:机敏、判断…

2026/7/10 0:00:01阅读更多 →
5分钟完全指南:如何使用TegraRcmGUI图形化工具解锁Switch无限可能

5分钟完全指南:如何使用TegraRcmGUI图形化工具解锁Switch无限可能

5分钟完全指南:如何使用TegraRcmGUI图形化工具解锁Switch无限可能 【免费下载链接】TegraRcmGUI C GUI for TegraRcmSmash (Fuse Gele exploit for Nintendo Switch) 项目地址: https://gitcode.com/gh_mirrors/te/TegraRcmGUI TegraRcmGUI是一款专为Windows…

2026/7/10 0:00:01阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/9 9:45:20阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/9 15:50:44阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/9 14:14:17阅读更多 →