platform驱动实战:设备树匹配与资源获取全流程 - 第1节

1.1 Platform 驱动概述

在 Linux 内核驱动框架中,Platform 驱动(平台驱动) 是一种虚拟总线驱动模型,用于管理那些不挂载在 PCI、USB、I2C、SPI 等物理总线上的设备。这些设备通常直接集成在 SoC 内部,或者通过内存映射 I/O 与 CPU 连接,例如:GPIO 控制器、时钟控制器、中断控制器、DMA 控制器、以太网 MAC 等。

核心概念:Platform 驱动模型将“设备”与“驱动”分离,通过 platform_driver 和 platform_device 两个核心数据结构,实现驱动与设备的动态匹配与绑定。

1.1.1 Platform 总线模型架构

Platform 驱动模型遵循 Linux 设备模型中的“总线-设备-驱动”三层架构。下图展示了 Platform 总线在系统中的位置与交互关系:

Platform 总线模型架构图 Linux 设备模型核心 Platform 总线 (platform_bus_type) 设备端 platform_device • name / id / num_resources • resource[] / dev.platform_data 驱动端 platform_driver • probe() / remove() / shutdown() • id_table / driver.of_match_table 匹配 (Match) 匹配成功后调用 probe(),驱动获得设备资源并初始化硬件 匹配依据:设备树 compatible 属性 / platform_device.name / ID 表

1.1.2 Platform 驱动的典型应用场景

场景类别 典型设备举例 说明
SoC 内部外设 UART、SPI、I2C 控制器、定时器 集成在芯片内部,无物理总线枚举
内存映射设备 GPIO 控制器、中断控制器、DMA 引擎 通过 MMIO 访问寄存器,地址在设备树中描述
非枚举型总线设备 板级 I2C/SPI 从设备(部分) 无法自动枚举,需设备树或板级代码描述
虚拟/伪设备 GPIO 按键、LED、看门狗 通常由设备树节点触发 platform_device 创建
关键认知:Platform 驱动并非只用于“平台设备”,它已成为 Linux 内核中管理 非可枚举设备 的标准抽象层。设备树(Device Tree)的引入,使得 platform_device 的创建和资源描述完全由设备树节点自动生成,驱动开发者只需关注 probe() 中的资源获取与硬件初始化。

1.2 设备树在驱动中的作用

设备树(Device Tree) 是一种描述硬件拓扑和资源的数据结构,以 .dts 源文件形式存在,编译为 .dtb 二进制后由 bootloader 传递给内核。设备树的核心作用在于:将硬件配置信息从内核代码中解耦,使得同一份内核镜像可以支持不同的硬件平台。

1.2.1 设备树如何影响 Platform 驱动

设备树与 Platform 驱动的交互贯穿整个驱动生命周期,从设备注册到资源获取,再到匹配与 probe:

设备树与 Platform 驱动交互流程 阶段 1:设备树解析 内核解析 DTB → 创建 device_node 生成 platform_device 链表 阶段 2:驱动注册 platform_driver_register() 填充 of_match_table 阶段 3:匹配 compatible 属性比对 匹配成功 → probe() 阶段 4:probe() 中获取设备树资源 of_iomap() / platform_get_resource() / of_property_read_*() 获取寄存器地址、中断号、DMA 通道、时钟、GPIO 等 设备树节点示例 myuart: serial@10001000 { compatible = "myvendor,my-uart"; reg = <0x10001000 0x1000>; interrupts = <0 33 4>; }; 最终效果:驱动与硬件完全解耦,更换硬件只需修改 DTS 无需重新编译内核,无需修改驱动源码

1.2.2 设备树提供的核心资源类型

资源类型 设备树属性 驱动获取 API 说明
寄存器地址/范围 reg platform_get_resource() / of_iomap() 描述 MMIO 基地址和大小
中断 interrupts platform_get_irq() 支持 SPI、PPI、边沿/电平触发
时钟 clocks devm_clk_get() 通过 phandle 引用时钟控制器
DMA dmas dma_request_chan() 描述 DMA 通道与请求线
GPIO gpios devm_gpiod_get() 通过 GPIO 描述符访问
自定义属性 任意自定义属性名 of_property_read_*() 读取整型、字符串、数组等
常见误区:设备树不是驱动配置文件的替代品。它描述的是 硬件拓扑 和 不可变资源,而非运行时参数。驱动运行时的可调参数应通过 sysfs、debugfs 或模块参数传递。

1.3 本课程学习目标与前置知识

1.3.1 学习目标

通过本课程的学习,你将能够:

  1. 理解 Platform 驱动模型:掌握 platform_driver、platform_device 的核心数据结构与生命周期。
  2. 掌握设备树语法与编译:能够编写 .dts 文件,使用 dtc 编译为 .dtb,并理解设备树在驱动匹配中的作用。
  3. 实现设备树匹配:在驱动中正确编写 of_match_table,实现 compatible 属性的精确匹配。
  4. 获取设备树资源:熟练使用 of_iomap()、platform_get_resource()、of_property_read_*() 等 API 获取寄存器、中断、时钟、GPIO 等资源。
  5. 编写完整的 Platform 驱动:从零开始实现一个基于设备树的 Platform 驱动,包含 probe()、remove()、PM 操作等完整流程。
  6. 调试与验证:通过 devicetree、sysfs、debugfs 等接口验证驱动与设备树的匹配状态。

1.3.2 前置知识要求

知识领域 具体要求 推荐掌握程度
C 语言编程 指针、结构体、回调函数、链表操作 熟练
Linux 内核基础 内核模块编写、编译、加载/卸载;printk 调试 入门
Linux 设备模型 kobject、sysfs、总线/设备/驱动模型基本概念 了解
嵌入式系统基础 ARM/ RISC-V 体系结构、MMIO、中断控制器基本概念 了解
设备树基础 .dts 文件结构、节点、属性、phandle 基本语法 了解(本课程会系统讲解)
学习建议:如果你对设备树语法尚不熟悉,不必担心。本课程第 2 章将系统讲解设备树语法与编译流程,第 3 章开始进入 Platform 驱动实战。建议在学习过程中准备一块支持设备树的开发板(如 QEMU virt 平台或 Raspberry Pi),边学边练效果最佳。

1.3.3 课程路线图

课程章节路线图 第 1-2 章 基础概念与设备树 第 3-5 章 驱动匹配与资源获取 第 6-8 章 完整驱动实战 第 9-10 章 调试与高级主题 每章均包含可运行的代码示例与实验步骤 建议按照章节顺序学习,逐步构建完整的 Platform 驱动知识体系
课程承诺:本课程不空谈理论,每一章都围绕“可运行的 Platform 驱动”展开。你将在第 3 章开始编写第一个基于设备树的驱动,并在第 6 章完成一个包含中断、时钟、DMA 资源获取的完整驱动实例。所有代码均在 QEMU virt 平台验证通过。