2. 设备驱动模型简介:总线、设备、驱动三者的关系,platform总线与设备树的基本概念
在Linux内核中,设备驱动模型是连接硬件与操作系统的核心架构。理解总线(Bus)、设备(Device)、驱动(Driver)三者之间的关系,是编写兼容性良好、可移植性强的驱动程序的基础。本章将深入剖析这一模型,并重点介绍嵌入式开发中至关重要的platform总线与设备树(Device Tree)。
2.1 核心三要素:总线、设备与驱动
Linux内核的设备模型采用面向对象的思想,将硬件资源抽象为三个核心对象。它们通过总线进行匹配与绑定,形成一个可动态管理的树状结构。
| 要素 | 内核数据结构 | 职责描述 |
|---|---|---|
| 总线 (Bus) | struct bus_type |
负责管理设备和驱动,提供匹配规则(match函数),是通信的通道。 |
| 设备 (Device) | struct device |
代表一个物理或虚拟的硬件实体,包含资源信息(如I/O地址、中断号)。 |
| 驱动 (Driver) | struct device_driver |
包含操作硬件的具体代码(probe/remove),负责初始化、控制设备。 |
核心机制:当系统注册一个新设备或新驱动时,内核会遍历对应总线上的驱动或设备列表,调用总线的
match函数进行匹配。匹配成功后,调用驱动的probe函数,完成设备初始化。
下图展示了总线、设备与驱动之间的核心交互流程:
2.2 platform总线:虚拟总线的诞生
在嵌入式系统中,许多设备(如UART、I2C控制器、GPIO)并不挂载在PCIe、USB等可枚举总线上。为了统一管理这些“非枚举型”设备,内核引入了platform总线(虚拟总线)。
- 本质:一个名为
platform_bus_type的虚拟总线实例,挂载在系统的虚拟根总线上。 - 匹配方式:通过设备名称(
name字段)或设备树中的compatible属性进行匹配。 - 资源传递:设备通过
struct platform_device携带内存地址、中断号等资源,驱动通过struct platform_driver获取并操作这些资源。
实战要点:绝大多数SoC内部集成的外设驱动,都是基于platform总线编写的。掌握platform驱动框架,是嵌入式Linux驱动开发的入门必修课。
2.3 设备树:硬件描述的“配置文件”
在引入设备树之前,内核中充斥着大量描述硬件信息的板级文件(board-*.c),导致内核臃肿且难以维护。设备树(Device Tree,DT)的出现,将硬件描述从内核代码中剥离出来,形成独立的.dts文件。
| 概念 | 文件后缀 | 说明 |
|---|---|---|
| DTS | .dts |
设备树源文件,由开发者编写,描述硬件拓扑和资源。 |
| DTSI | .dtsi |
设备树头文件,用于存放SoC公共硬件描述,可被多个DTS包含。 |
| DTB | .dtb |
编译后的二进制文件,由Bootloader加载并传递给内核。 |
| DTBO | .dtbo |
设备树叠加层,用于运行时动态修改设备树。 |
设备树的核心语法如下:
/dts-v1/;
#include "imx6ull.dtsi"
/ {
model = "Embedded Device Board";
compatible = "vendor,board-name";
my_uart: uart@02020000 {
compatible = "vendor,my-uart";
reg = <0x02020000 0x4000>;
interrupts = <0 58 4>;
status = "okay";
};
};
关键字段解析:
compatible:驱动匹配的核心标识,格式通常为“厂商,设备名”。reg:描述设备占用的地址空间(起始地址 + 长度)。interrupts:描述设备使用的中断号、触发类型等。
2.4 设备树与platform总线的协同工作
设备树与platform总线紧密配合,构成了现代嵌入式Linux驱动的基础设施。内核在启动时解析DTB,为每个compatible属性匹配的节点创建platform_device,然后挂载到platform总线上等待驱动匹配。
常见误区:设备树中的
compatible属性必须与驱动中of_match_table定义的字符串完全一致,包括大小写和标点符号。一个字符的差异就会导致匹配失败,驱动无法加载。
2.5 本章小结
- 总线、设备、驱动是Linux设备模型的三大支柱,通过
match和probe机制实现解耦与动态绑定。 - platform总线解决了非枚举设备的统一管理问题,是嵌入式驱动开发的核心框架。
- 设备树将硬件描述从内核代码中分离,提高了内核的可移植性和可维护性。
- 设备树节点最终被内核解析为
platform_device,与platform_driver在platform总线上完成匹配。