20260122 - Linux驱动学习笔记:分层与解耦
·
Linux 设备驱动模型(Device Model)的核心设计哲学:分层与解耦。
1. 数据的源头:设备树 (DTS)
硬件工程师在设备树里写好硬件的参数。
在设备树文件中:
&ecspi1 {
// ... 控制器配置 ...
dac: dac {
compatible = "spidev"; // 用于匹配驱动
reg = <0>; // 对应片选 CS0
spi-max-frequency = <20000000>; // 对应 20MHz
};
};
2. 数据的搬运工:SPI Core 层 (drivers/spi/spi.c)
在系统启动(或者动态加载设备树)时,Linux 内核的 SPI 核心层会做以下几件事,这些动作发生在 spidev_probe 被调用之前:
- 解析 (Parse):SPI Core 读取设备树的二进制文件(DTB)。
- 分配 (Allocate):它会调用
spi_alloc_device为dac这个节点分配一块内存,也就是struct spi_device。 - 填充 (Populate):它把 DTS 里的属性,“搬运”到 C 语言的结构体里。
- DTS
reg = <0>==> C structspi->chip_select = 0; - DTS
spi-max-frequency = <20000000>==> C structspi->max_speed_hz = 20000000; - DTS
compatible = "spidev"==> C structspi->modalias(用于匹配)
- DTS
- 注册 (Register):将填好的
spi_device注册到系统总线上。
3. 数据的消费者:Driver 层 (spidev_probe)
当 SPI Core 发现 spi_device (设备) 和 spidev_driver (驱动) 匹配成功后,它会调用 probe,并把那个已经填满了数据的结构体指针传给你。
static int spidev_probe(struct spi_device *spi)
{
// 此时,spi 指针指向的内存区域里,
// spi->max_speed_hz 已经被 Core 层赋值为 20000000 了
// spi->chip_select 已经被 Core 层赋值为 0 了
spidev->speed_hz = spi->max_speed_hz; // 驱动把 Core 给的数据,存入自己的私有数据中
}
[图解] 数据流向全景
为了让你看得更清楚,我为你整理了一个一一映射表,你可以直接对应查看:
| 数据来源 (设备树 DTS) | 负责解析的内核文件 | 数据去向 (spi_device 结构体) | 最终在 spidev_probe 中的表现 |
|---|---|---|---|
Node: dac { ... } |
drivers/spi/spi.c |
struct spi_device *spi |
probe 函数的入参 spi |
Prop: spi-max-frequency = <20000000> |
drivers/spi/spi.c |
spi->max_speed_hz |
spi->max_speed_hz 值为 20000000 |
Prop: reg = <0> |
drivers/spi/spi.c |
spi->chip_select |
spi->chip_select 值为 0 |
Parent: &ecspi1 |
drivers/spi/spi.c |
spi->master |
spi->master->bus_num (比如 1) |
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)